Tomcat 8和Spring Security Cors

5

我正在尝试配置 Spring Security 以支持CORS。

在这篇文章Spring security CORS Filter的帮助下,我使用以下配置代码成功地将其应用于我的本地 Spring Boot 服务器:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors()
        .and()
        .antMatcher("/api/**")
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers(HttpMethod.POST, "/api/login").permitAll()
        .antMatchers(HttpMethod.GET, "/api/websocket/**").permitAll()
        .antMatchers("/api/**").authenticated()
        .and()
        .addFilterBefore(new JWTLoginFilter("/api/login", HttpMethod.POST, authenticationManager(), tokenAuthenticationService, myUserService), UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(new JWTAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class)
        .csrf().disable();
    }

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

但是当我在远程Tomcat服务器上部署我的应用程序时,它不能正常工作:

 Access to XMLHttpRequest at 'http://xxx:9080/yyy/api/user/findByLogin/?login=zzz' from origin 'http://xxx:10080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这是一个失败的OPTIONS请求的截图: enter image description here 这是我的本地主机上工作的请求: enter image description here 我的配置类是否足够?还是我需要在Tomcat设置中进行一些配置? 谢谢

你能检查一下你的 OPTIONS 请求是否会导致 CORS 错误吗?如果是,将它添加到你允许的方法中,然后再试一次。 - Viswa
你能看一下这篇文章吗?https://dev59.com/GKHia4cB1Zd3GeqPRlXz - Viswa
你的pom.xml和主类是什么样子?请尝试提供一个[mcve]。 - Selaron
为什么你的corsConfigurationSource中没有允许OPTIONS方法? - amant singh
只是为了实验,尝试设置AllowedOrigins的确切值,而不是通配符:configuration.setAllowedOrigins(ImmutableList.of("http://xxx:10080", "http://localhost:8082")); - Eugene Khyst
显示剩余6条评论
7个回答

1

Spring Security提供了一种在http配置器中配置CORS的方法,但是有一种更简洁的方法是向应用程序添加CORS过滤器-

@Component 
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyCORSFilterClass implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}
}

将具有最高优先级的过滤器订购可以确保 MyCORSFilterClass 实现 javax.servlet.Filter 的过滤器是链中的第一个。


1
使用过滤器时,它在本地工作正常(如果在WebSecurityConfigurerAdapter中添加http.cors()),但在我的Tomcat服务器上仍然无法工作。 - Clément Picou
1
我也遇到了同样的问题。@ClémentPicou 有解决方案吗? - Harshad Chhaiya

0
  1. 尝试在本地的corsConfigurationSource()方法中设置一个调试断点,并检查是否被执行。如果没有被执行,请调查原因 - 可能是通过启用Spring的调试日志和/或重新检查Spring配置。

  2. 另外,尝试将OPTIONS添加到setAllowedMethods

    configuration.setAllowedMethods(ImmutableList.of("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
    

0
  1. 你的允许方法也应该有"OPTIONS"。
  2. 你拥有这个web服务器吗?这个web服务器也有CORS的可能吗?

0

Tomcat也有自己的CORS过滤器,如果您在Tomcat之前使用其他服务器(如Node.js、Apache服务器等),请检查它们的CORS过滤器。


0

检查一下Tomcat服务器是否在$CATALINA_BASE/conf/web.xml中配置了冲突的CORS过滤器。


0

响应代码403表示授权失败。可能是您的服务器设置了对选项请求进行授权。您必须确保选项已配置为发送成功响应(2xx状态代码),以允许浏览器发送实际请求。 2xx响应通知浏览器服务器处理CORS请求。

您的请求在本地工作的原因可能是您在发出请求时已经获得了授权。因此,请检查您的身份验证以确保其正确。因此,预检请求不会发送任何授权标头,因此您不应该在服务器端期望它们。


0

只需配置CorsFilter即可添加相关的CORS响应头(如Access-Control-Allow-Origin),使用提供的CorsConfigurationSource。阅读其文档以获取更多信息。由于您已经拥有UrlBasedCorsConfigurationSource,因此可以像下面这样配置过滤器:

@Bean
  public FilterRegistrationBean corsFilter() {
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(corsConfigurationSource()));
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;
  }

只需在您的配置文件中添加上述bean,希望它能正常工作。

这是完整的配置文件,您只需要像上面提到的那样使用其中的一部分即可:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接