jquery spring tomcat spring-security cors

jquery - Problema de CORS: no hay un encabezado ''Access-Control-Allow-Origin'' presente en el recurso solicitado



spring tomcat (3)

Desde Spring Security 4.1, esta es la forma correcta de hacer que Spring Security sea compatible con CORS (también se necesita en Spring Boot 1.4 / 1.5):

@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH"); } }

y:

@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // http.csrf().disable(); http.cors(); } @Bean public CorsConfigurationSource corsConfigurationSource() { final CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(ImmutableList.of("*")); configuration.setAllowedMethods(ImmutableList.of("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH")); // setAllowCredentials(true) is important, otherwise: // The value of the ''Access-Control-Allow-Origin'' header in the response must not be the wildcard ''*'' when the request''s credentials mode is ''include''. configuration.setAllowCredentials(true); // setAllowedHeaders is important! Without it, OPTIONS preflight request // will fail with 403 Invalid CORS request configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type")); final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }

No haga nada de lo siguiente, que son la forma incorrecta de intentar resolver el problema:

  • http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
  • web.ignoring().antMatchers(HttpMethod.OPTIONS);

Referencia: http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html

He creado dos aplicaciones web: aplicaciones de cliente y de servicio.
La interacción entre las aplicaciones de cliente y servicio funciona bien cuando se implementan en la misma instancia de Tomcat.
Pero cuando las aplicaciones se implementan en instancias separadas de Tomcat (máquinas diferentes), recibo el siguiente error cuando solicito la aplicación de servicio enviada.

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

La aplicación Mi cliente utiliza JQuery, HTML5 y Bootstrap.

La llamada AJAX se realiza al servicio como se muestra a continuación:

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 ); }); }

Mi aplicación de servicio utiliza Spring MVC, Spring Data JPA y Spring Security.

He incluido la clase CorsConfiguration como se muestra a continuación:

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; } }

Dependencias 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>

Estoy usando el servidor Apache Tomcat para la implementación.


En mi caso, tengo el servidor de recursos con la seguridad de OAuth habilitada y ninguna de las soluciones anteriores funcionó. Después de un poco de depuración y googleo descubrí por qué.

@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; }

Básicamente, en este ejemplo, Ordered.HIGHEST_PRECEDENCE es clave.

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

Varias dependencias de pom agregan diferentes tipos de filtros y, por lo tanto, podríamos tener problemas según el orden.


La solicitud de verificación previa de CORS utiliza OPTIONS HTTP sin credenciales, consulte Intercambio de recursos de origen cruzado :

De lo contrario, haga una solicitud de verificación previa . Obtenga la URL de solicitud del origen de origen utilizando la fuente de referencia como fuente de referencia de anulación con el indicador de redireccionamiento manual y el conjunto de indicadores de bloqueo de cookies, utilizando el método OPTIONS, y con las siguientes restricciones adicionales:

  • Incluya un encabezado Método de solicitud de control de acceso con el valor del campo de encabezado como método de solicitud (incluso cuando sea un método simple).
  • Si los encabezados de solicitud de autor no están vacíos, incluya un encabezado de Access-Control-Request-Headers con un valor de campo de encabezado, una lista separada por comas de los nombres de campo de encabezado de los encabezados de solicitud de autor en orden lexicográfico, cada uno convertido a ASCII en minúscula (incluso cuando uno o más son un encabezado simple).
  • Excluir los encabezados de solicitud de autor.
  • Excluir credenciales de usuario.
  • Excluir el cuerpo de la entidad de solicitud.

Debe permitir el acceso anónimo para las OPTIONS HTTP.

Su código modificado (y simplificado):

@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(); }

Desde Spring Security 4.2.0 puede usar el soporte incorporado, consulte la Referencia de Spring Security :

19. CORS

Spring Framework proporciona soporte de primera clase para CORS. CORS debe procesarse antes de Spring Security porque la solicitud previa al vuelo no contendrá ninguna cookie (es decir, el JSESSIONID ). Si la solicitud no contiene cookies y Spring Security es lo primero, determinará que el usuario no está autenticado (ya que no hay cookies en la solicitud) y la rechazará.

La manera más fácil de garantizar que CORS se maneje primero es usar el CorsFilter . Los usuarios pueden integrar el CorsFilter con Spring Security al proporcionar un CorsConfigurationSource utilizando lo siguiente:

@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; } }