web-dev-qa-db-fra.com

Problème CORS - Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée

J'ai créé deux applications Web - les applications client et service.
L'interaction entre les applications client et les applications de service se passe bien lorsqu'elles sont déployées dans la même instance Tomcat.
Mais lorsque les applications sont déployées dans des instances distinctes de Tomcat (machines différentes), j'obtiens l'erreur ci-dessous lors de la demande d'envoi de l'application de service.

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 401

L'application My Client utilise JQuery, HTML5 et Bootstrap.

Un appel AJAX est effectué pour le service comme indiqué ci-dessous:

var auth = "Basic " + btoa({usname} + ":" + {password});
var service_url = {serviceAppDomainName}/services;

if($("#registrationForm").valid()){
    var formData = JSON.stringify(getFormData(registrationForm));
    $.ajax({
        url: service_url+action,
        dataType: 'json',
        async: false,
        type: 'POST',
        headers:{
            "Authorization":auth
        },
        contentType: 'application/json',
        data: formData,
        success: function(data){
            //success code
        },
        error: function( jqXhr, textStatus, errorThrown ){
            alert( errorThrown );
        });
}

Mon application de service utilise Spring MVC, Spring Data JPA et Spring Security.

J'ai inclus la classe CorsConfiguration comme indiqué ci-dessous:

CORSConfig.Java:

@Configuration
@EnableWebMvc
public class CORSConfig extends WebMvcConfigurerAdapter  {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("*");
    }
}

SecurityConfig.Java:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@ComponentScan(basePackages = "com.services", scopedProxy = ScopedProxyMode.INTERFACES)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("authenticationService")
    private UserDetailsService userDetailsService;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(authenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().fullyAuthenticated();
        http.httpBasic();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.csrf().disable();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }
}

Dépendances de Spring Security:

 <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>3.2.3.RELEASE</version>
</dependency>
<dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>3.2.3.RELEASE</version>
</dependency>

J'utilise Apache Tomcat server pour le déploiement.

12
JavaDeveloper

La requête de contrôle en amont de CORS utilise HTTP OPTIONS sans informations d'identification, voir Partage de ressources d'origine croisée :

Sinon, faites une demande preflight. Récupérez l'URL de la demande à partir de la source d'origine Origin en utilisant la source de référent comme source de référent avec l'indicateur de redirection manuelle et l'indicateur de cookies de blocage définis, à l'aide de la méthode OPTIONS et avec les contraintes supplémentaires suivantes:

  • Incluez un en-tête Access-Control-Request-Method avec comme champ la valeur de la méthode request (même s’il s’agit d’une méthode simple).
  • Si les en-têtes de demande d’auteur ne sont pas vides, incluez un en-tête Access-Control-Request-Headers avec comme valeur de champ d’en-tête une liste séparée par des virgules des noms de champ d’en-tête des en-têtes de demande d’auteur dans l’ordre lexicographique, chacun converti en minuscule ASCII même quand un ou plusieurs sont un simple en-tête).
  • Exclure les en-têtes de demande d’auteur.
  • Exclure les informations d'identification de l'utilisateur.
  • Exclure le corps d'entité de la demande.

Vous devez autoriser l'accès anonyme pour HTTP OPTIONS

Votre code modifié (et simplifié):

@Override
protected void configure(HttpSecurity http) throws Exception {
   http
       .authorizeRequests()
           .andMatchers(HttpMethod.OPTIONS, "/**").permitAll()
           .antMatchers("/login").permitAll()
           .anyRequest().fullyAuthenticated()
           .and()
       .httpBasic()
           .and()
       .sessionManagement()
           .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
           .and()
       .csrf().disable();
}

Depuis Spring Security 4.2.0, vous pouvez utiliser le support intégré, voir Référence de sécurité Spring :

19. CORS

Spring Framework fournit un support de première classe pour CORS. La CORS doit être traitée avant la sécurité Spring, car la demande de pré-vol ne contiendra aucun cookie (c.-à-d. La JSESSIONID). Si la demande ne contient pas de cookies et que Spring Security est le premier, la demande déterminera que l'utilisateur n'est pas authentifié (car il n'y a pas de cookies dans la demande) et la rejettera.

Le moyen le plus simple de s’assurer que CORS est traité en premier est d’utiliser la variable CorsFilter. Les utilisateurs peuvent intégrer la CorsFilter à Spring Security en fournissant une CorsConfigurationSource en utilisant les éléments suivants:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http
          // by default uses a Bean by the name of corsConfigurationSource
          .cors().and()
          ...
  }

  @Bean
  CorsConfigurationSource corsConfigurationSource() {
      CorsConfiguration configuration = new CorsConfiguration();
      configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
      configuration.setAllowedMethods(Arrays.asList("GET","POST"));
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      source.registerCorsConfiguration("/**", configuration);
      return source;
  }
}
10
dur

Dans mon cas, le serveur de ressources avec la sécurité OAuth est activé et les solutions ci-dessus ne fonctionnent pas. Après un peu de débogage et googler compris pourquoi. 

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;
}

Fondamentalement, dans cet exemple, Ordered.HIGHEST_PRECEDENCE est la clé! 

https://github.com/spring-projects/spring-security-oauth/issues/938

Différentes dépendances de pom ajoutent différents types de filtres et par conséquent, nous pourrions avoir des problèmes liés à l'ordre.

0
AntonIva