Spring Boot安全性CORS

我对弹簧安全URL的CORSfilter有问题。 它不会在属于spring sec(登录/注销)的URL上设置Access-Control-Allow-Origin和其他公开的标头,也不会被Spring Security过滤。

这是配置。

CORS:

 @Configuration @EnableWebMvc public class MyWebMvcConfig extends WebMvcConfigurerAdapter { ********some irrelevant configs************ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/*").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT") .allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers") .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials") .allowCredentials(true).maxAge(3600); } } 

安全:

 @Configuration @EnableWebSecurity public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and() .formLogin() .successHandler(ajaxSuccessHandler) .failureHandler(ajaxFailureHandler) .loginProcessingUrl("/authentication") .passwordParameter("password") .usernameParameter("username") .and() .logout() .deleteCookies("JSESSIONID") .invalidateHttpSession(true) .logoutUrl("/logout") .logoutSuccessUrl("/") .and() .csrf().disable() .anonymous().disable() .authorizeRequests() .antMatchers("/authentication").permitAll() .antMatchers("/oauth/token").permitAll() .antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')") .antMatchers("/user/*").access("hasRole('ROLE_USER')"); } } 

因此,如果我向未被安全性监听的url发出请求,则会设置CORS标头。 Spring安全URL – 未设置。

Spring boot 1.4.1

您可以编写自己的CorsFilter,并将其添加到安全配置中,而不是使用CorsRegistry。

自定义CorsFilter类:

 public class CorsFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) servletResponse; HttpServletRequest request= (HttpServletRequest) servletRequest; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "*"); response.setHeader("Access-Control-Allow-Credentials", true); response.setHeader("Access-Control-Max-Age", 180); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } 

安全配置类:

 @Configuration @EnableWebSecurity public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean CorsFilter corsFilter() { CorsFilter filter = new CorsFilter(); return filter; } @Override protected void configure(HttpSecurity http) throws Exception { http .addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and() .formLogin() .successHandler(ajaxSuccessHandler) .failureHandler(ajaxFailureHandler) .loginProcessingUrl("/authentication") .passwordParameter("password") .usernameParameter("username") .and() .logout() .deleteCookies("JSESSIONID") .invalidateHttpSession(true) .logoutUrl("/logout") .logoutSuccessUrl("/") .and() .csrf().disable() .anonymous().disable() .authorizeRequests() .antMatchers("/authentication").permitAll() .antMatchers("/oauth/token").permitAll() .antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')") .antMatchers("/user/*").access("hasRole('ROLE_USER')"); } } 

选项1(使用WebMvcConfigurer bean):

您开始使用的CORS配置不是使用Spring Boot执行此操作的正确方法。 您需要注册WebMvcConfigurer bean。 参考这里 。

示例Spring Boot CORS配置:

 @Configuration @Profile("dev") public class DevConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("http://localhost:4200"); } }; } } 

这将为基本(无安全启动器)Spring Boot应用程序提供CORS配置。 请注意,CORS支持独立于Spring Security。

一旦引入Spring Security,您需要在安全配置中注册CORS。 Spring Security足够聪明,可以获取现有的CORS配置。

 @Override protected void configure(HttpSecurity http) throws Exception { http .cors().and() .... 

选项2(使用CorsConfigurationSource bean):

我描述的第一个选项实际上是从向现有应用程序添加Spring Security的角度出发的。 如果您要从一开始就添加Spring Security,那么Spring Security Docs中概述的方式涉及添加CorsConfigurationSource bean。

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

我有一个基于React的Web客户端,我的后端REST API正在运行Spring Boot Ver 1.5.2

我想在运行在localhost:8080上的客户端的所有控制器路由请求上快速启用CORS 。 在我的安全配置中,我只是添加了一个类型为FilterRegistrationBean@Bean ,并使其易于使用。

这是代码:

 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class AuthConfiguration extends WebSecurityConfigurerAdapter { .... .... @Bean public FilterRegistrationBean corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin(corsAllowedOrigin); // @Value: http://localhost:8080 config.addAllowedHeader("*"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean; } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // **permit OPTIONS call to all** .... } .... .... } 

您可以在此处参考Spring Boot 文档

您也可以使用拦截器实现此目的。

使用该例外可确保您结束请求的生命周期:

 @ResponseStatus ( value = HttpStatus.NO_CONTENT ) public class CorsException extends RuntimeException { } 

然后,在您的拦截器中,为所有OPTIONS请求设置标头并抛出exception:

 public class CorsMiddleware extends HandlerInterceptorAdapter { @Override public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler ) throws Exception { if (request.getMethod().equals("OPTIONS")) { response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Credentials", "true"); response.addHeader("Access-Control-Allow-Methods","GET, POST, PUT, OPTIONS, DELETE"); response.addHeader("Access-Control-Allow-Headers", "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,Authorization,If-Modified-Since,Cache-Control,Content-Type"); response.addHeader("Access-Control-Max-Age", "3600"); response.addHeader("charset", "utf-8"); throw new CorsException(); } return super.preHandle(request, response, handler); } } 

最后,将拦截器应用于所有路由:

 @Configuration public class MiddlewareConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(new CorsMiddleware()) .addPathPatterns("/**"); } } 

如果您需要它来进行快速本地开发,只需在控制器上添加此注释即可。 (根据需要改变原因)

 @CrossOrigin(origins = "http://localhost:4200", maxAge = 3600) 

目前,如果启用了安全性,则默认情况下会阻止OPTIONS请求。

只需添加一个额外的bean,就可以正确处理预检请求:

  @Bean public IgnoredRequestCustomizer optionsIgnoredRequestsCustomizer() { return configurer -> { List matchers = new ArrayList<>(); matchers.add(new AntPathRequestMatcher("/**", "OPTIONS")); configurer.requestMatchers(new OrRequestMatcher(matchers)); }; } 

请注意,根据您的应用程序,这可能会打开它以获取潜在的攻击。

打开问题以获得更好的解决方案: https : //github.com/spring-projects/spring-security/issues/4448