Spring Security CORS 过滤器不起作用

Posted

技术标签:

【中文标题】Spring Security CORS 过滤器不起作用【英文标题】:Spring Security CORS filter not working 【发布时间】:2016-11-10 01:13:07 【问题描述】:

我正在使用带有 OAuth2(版本:4.0.4.RELEASE)和 spring(版本:4.3.1.RELEASE)的 Spring Security。

我正在使用 Angular 开发前端,并且正在使用 grunt connect:dev (http://127.0.0.1:9000)。当我尝试通过本地主机地址登录时,一切正常,但从其他我收到错误:

“XMLHttpRequest 无法加载 http://localhost:8084/oauth/token?client_id=MY_CLIENT_ID。对预检请求的响应未通过访问控制检查:请求的资源上不存在 'Access-Control-Allow-Origin' 标头。因此不存在来源 'http://127.0.0.1:9000'允许访问。响应的 HTTP 状态代码为 401。"

我已经在 WebMvcConfigurerAdapter 中配置了映射(Overrided public void addCorsMappings(CorsRegistry registry))(如下所示),但它仍然不适用于http://127.0.0.1:9000。

    registry.addMapping("/**")
            .allowedOrigins("http://127.0.0.1:9000")
            .allowedMethods("POST", "OPTIONS", "GET", "DELETE", "PUT")
            .allowedHeaders("X-Requested-With,Origin,Content-Type,Accept,Authorization")
            .allowCredentials(true).maxAge(3600);

配置基于:https://spring.io/guides/gs/rest-service-cors/

请给我指出正确的方向来解决这个问题。

【问题讨论】:

如果我理解正确,您正在尝试从不同的 ip 127.0.0.1 访问。 (您不再在本地主机中)。但是您只允许从 localhost (127.0.0.1) 访问 Spring CORS No 'Access-Control-Allow-Origin' header is present的可能重复 Periklis - 是的,我正在尝试从不同的 IP 访问。我只能从localhost:8084 获得许可。 Oleg Kurbatov - 谢谢,我知道这个链接,但所有内容都来自文档。我完成了文档中的所有操作,但仍然无法正常工作。在我的配置中,我不使用 web.xml 订购过滤器怎么样?有什么想法吗? 【参考方案1】:

下面对我有用。

  import org.springframework.context.annotation.Configuration;
  import org.springframework.web.servlet.config.annotation.CorsRegistry;
  import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

  @Configuration
  @EnableWebMvc
  public class MvcConfig implements WebMvcConfigurer 

  @Override
  public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**").allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");     
  

【讨论】:

【参考方案2】:

抱歉长时间回复。我通过如下配置我的 CORS 过滤器解决了这个问题:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter 

    private static final Logger LOGGER = LogManager.getLogger(CORSFilter.class.getName());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
    

    @Override
    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException 
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;
        final String origin = ((HttpServletRequest) req).getHeader("Origin");

        if (ofNullable(origin).isPresent() && origin.equals("http://127.0.0.1:9000")) 
            LOGGER.info("CORSFilter run");
            response.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:9000");
            response.addHeader("Access-Control-Allow-Credentials", "true");

            if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) 
                response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                response.addHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Authorization");
                response.setStatus(200);
            
        
        chain.doFilter(addNessesaryHeaders(request), response);
    


    private MutableHttpServletRequest addNessesaryHeaders(final HttpServletRequest request) 
        final MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(request);
        mutableRequest.putHeader("Accept", "application/json");
        mutableRequest.putHeader("Authorization", "Basic" + " bXVzaWNzY2hvb2w6");
        return mutableRequest;
    

    @Override
    public void destroy() 
    

【讨论】:

【参考方案3】:

希望您很久以前就找到了答案,但如果没有(如果其他人发现这个问题像我一样搜索):

问题在于 Spring Security 使用过滤器进行操作,这些过滤器通常优先于用户定义的过滤器、@CrossOrigin 和类似的注释等。

对我有用的是将 CORS 过滤器定义为具有最高优先级的 bean,正如 here 所建议的那样。

@Configuration
public class MyConfiguration 

    @Bean
    public FilterRegistrationBean corsFilter() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://127.0.0.1:9000");
        config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT"));
        config.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    

【讨论】:

帮我解决了问题。但是,FilterRegistrationBean 是参数化的【参考方案4】:

你可以试试这样的

@Configuration
public class CorsConfig 
   @Bean
   public WebMvcConfigurer corsConfigurer() 
        return new WebMvcConfigurerAdapter() 
          @Override
          public void addCorsMappings(CorsRegistry registry) 
            registry.addMapping("/**")
                    .allowedMethods(HttpMethod.OPTIONS.name(),
                            HttpMethod.PATCH.name(),
                            HttpMethod.PUT.name(),
                            HttpMethod.DELETE.name(),
                            HttpMethod.GET.name(),
                            HttpMethod.POST.name())
                    .maxAge(360);
            
       ;
   

注意:Spring 版本应为 4.2 或更高版本

【讨论】:

你可以尝试添加:.allowedHeaders("header1", "header2"),接受头变量发送到服务器。 您的问题解决了吗?如果是,请您提供解决方案,即使我在我的应用程序中也面临同样的错误。

以上是关于Spring Security CORS 过滤器不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Security 过滤器中授权 CORS

Tomcat CORS 过滤器和 Spring Security

spring security CORS 过滤器允许没有“Origin”标头的请求

身份验证过滤器之前的 CORS 过滤器 - 不太安全? Spring Security 过滤器链序

添加了 Spring Security CORS 过滤器 - 从 DB 检索的日期显示在数值中

添加了 Spring Security CORS 过滤器 - 从 DB 检索的日期显示在数值中