【问题标题】:Spring security CORS Filter弹簧安全CORS过滤器
【发布时间】:2017-03-18 00:54:17
【问题描述】:

我们在现有项目中添加了Spring Security

从这一刻起,我们的服务器收到 401 No 'Access-Control-Allow-Origin' header is present on the requested resource 错误。

这是因为响应中没有附加 Access-Control-Allow-Origin 标头。为了解决这个问题,我们在注销过滤器之前的Filter 链中添加了我们自己的过滤器,但该过滤器不适用于我们的请求。

我们的错误:

XMLHttpRequest 无法加载 http://localhost:8080/getKunden。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin http://localhost:3000 不允许访问。响应的 HTTP 状态代码为 401。

我们的安全配置:

@EnableWebSecurity
@Configuration
@ComponentScan("com.company.praktikant")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private MyFilter filter;

@Override
public void configure(HttpSecurity http) throws Exception {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();

    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    source.registerCorsConfiguration("/**", config);
    http.addFilterBefore(new MyFilter(), LogoutFilter.class).authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/*").permitAll();
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
}
}

我们的过滤器

@Component
public class MyFilter extends OncePerRequestFilter {

@Override
public void destroy() {

}

private String getAllowedDomainsRegex() {
    return "individual / customized Regex";
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    final String origin = "http://localhost:3000";

    response.addHeader("Access-Control-Allow-Origin", origin);
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Headers",
            "content-type, x-gwt-module-base, x-gwt-permutation, clientid, longpush");

    filterChain.doFilter(request, response);

}
}

我们的应用程序

@SpringBootApplication
public class Application {
public static void main(String[] args) {
    final ApplicationContext ctx = SpringApplication.run(Application.class, args);
    final AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
    annotationConfigApplicationContext.register(CORSConfig.class);
    annotationConfigApplicationContext.refresh();
}
}

我们的过滤器是从 spring-boot 注册的:

2016-11-04 09:19:51.494 INFO 9704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean:将过滤器:“myFilter”映射到:[/*]

我们生成的过滤器链:

2016-11-04 09:19:52.729 INFO 9704 --- [ost-startStop-1] ossweb.DefaultSecurityFilterChain:创建过滤器链:org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5d8c5a8a, org.springframework.security.web.context.SecurityContextPersistenceFilter@7d6938f, org.springframework.security.web.header.HeaderWriterFilter@72aa89c, org.springframework .security.web.csrf.CsrfFilter@4af4df11, com.company.praktikant.MyFilter@5ba65db2, org.springframework.security.web.authentication.logout.LogoutFilter@2330834f, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@396532d1 , org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4fc0f1a2, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2357120f, org.springframework.security.web.session.SessionManagementFilter@10867bfb, org.springframework.security.web .access.E xceptionTranslationFilter@4b8bf1fb, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@42063cf1]

回应: Response headers

我们也尝试了 spring 的解决方案,但没有奏效!我们控制器中的注解 @CrossOrigin 也没有帮助。

编辑 1:

尝试了@Piotr Sołtysiak 的解决方案。 cors 过滤器未列在生成的过滤器链中,我们仍然得到相同的错误。

2016-11-04 10:22:49.881 INFO 8820 --- [ost-startStop-1] ossweb.DefaultSecurityFilterChain:创建过滤器链:org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4c191377, org.springframework.security.web.context.SecurityContextPersistenceFilter@28bad32a, org.springframework.security.web.header.HeaderWriterFilter@3c3ec668, org.springframework .security.web.csrf.CsrfFilter@288460dd, org.springframework.security.web.authentication.logout.LogoutFilter@1c9cd096, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@3990c331, org.springframework.security.web.authentication .ui.DefaultLoginPageGeneratingFilter@1e8d4ac1, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@2d61d2a4, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@380d9a9b, org.springframework.security.web.servletapi.SecurityContextHo lderAwareRequestFilter@abf2de3, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2a5c161b, org.springframework.security.web.session.SessionManagementFilter@3c1fd3e5, org.springframework.security.web.access.ExceptionTranslationFilter@3d7055ef, org.springframework。 security.web.access.intercept.FilterSecurityInterceptor@5d27725a]

顺便说一句,我们使用的是 spring-security 版本 4.1.3。!

【问题讨论】:

  • Chrome 存在问题,它不支持 localhost 通过 Access-Control-Allow-Origin。换个浏览器试试
  • 我们尝试使用 Edge,它可以正常工作...但 Firefox 不能正常工作。
  • 我遇到了同样的问题,我通过将127.0.0.1 localhost local.net 添加到/etc/hosts 然后调用local.net:8080/getKunden 来解决它
  • 请参阅stackoverflow.com/questions/28547288/… 它会有所帮助

标签: java spring spring-security spring-boot cors


【解决方案1】:

从 Spring Security 4.1 开始,这是使 Spring Security 支持 CORS 的正确方法(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");
    }
}

和:

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

不要不要做以下任何一种尝试解决问题的错误方法:

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

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

【讨论】:

  • 如果你不使用 Guava,你可以随时这样做:Collections.unmodifiableList(Arrays.asList("HEAD",...))
  • 请注意,WebMvcConfigurerAdapter 现在已弃用。
  • 不要在不知道自己在做什么的情况下删除 CSRF! owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
  • 仍然无法使用此解决方案,导致预检请求被阻止。
  • WebMvcConfigurerAdapter 类型已弃用。从 Spring 5 开始你只需要实现接口WebMvcConfigurer
【解决方案2】:

由于我在使用其他解决方案时遇到了问题(特别是为了让它在所有浏览器中都能正常工作,例如 edge 无法将“*”识别为“Access-Control-Allow-Methods”的有效值),我不得不使用自定义过滤器组件,它最终对我有用,并且完全符合我的要求。

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods",
                "ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, Key, Authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    public void init(FilterConfig filterConfig) {
        // not needed
    }

    public void destroy() {
        //not needed
    }

}

【讨论】:

  • 这里也一样。不过不得不用 X-Authorization 替换 Authorization。
  • 我为什么选择这个解决方案:因为我有 AuthorizationFilter 它在 CorsBean 之前响应,因此所有 Cors 预检请求都由 AuthFilter 响应,而不是 Spring Cors 配置。因此我用这个解决方案中提到的 CorsFilter 替换了 CorsConfig bean;现在 Cors 飞行前请求由 CorsFilter 按预期回答。 @大卫谢谢。
【解决方案3】:

好的,经过 2 多天的搜索,我们终于解决了这个问题。我们删除了所有过滤器和配置,而是在应用程序类中使用了这 5 行代码。

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        final ApplicationContext ctx = SpringApplication.run(Application.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:3000");
            }
        };
    }
}

【讨论】:

  • 您使用的是什么类型的身份验证?基本,形式?
【解决方案4】:

使用 Spring Boot 2 中的 Spring Security 全局配置 CORS(例如启用所有开发请求),您可以:

@Bean
protected CorsConfigurationSource corsConfigurationSource() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
    return source;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors()
            .and().authorizeRequests()
            .anyRequest().permitAll()
            .and().csrf().disable();
}

【讨论】:

    【解决方案5】:
    1. 你不需要:

      @Configuration
      @ComponentScan("com.company.praktikant")
      

      @EnableWebSecurity 里面已经有@Configuration,我无法想象你为什么把@ComponentScan 放在那里。

    2. 关于 CORS 过滤器,我只想说:

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

      进入 SecurityConfiguration 类并删除配置和配置全局方法。您不需要设置两次允许的来源、标题和方法。特别是如果您在过滤器和弹簧安全配置中放置不同的属性:)

    3. 根据上述,您的“MyFilter”类是多余的。

    4. 您也可以删除这些:

      final AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
      annotationConfigApplicationContext.register(CORSConfig.class);
      annotationConfigApplicationContext.refresh();
      

      来自应用程序类。

    5. 最后的小建议 - 与问题无关。您不想将动词放在 URI 中。而不是http://localhost:8080/getKunden,您应该在http://localhost:8080/kunden 资源上使用HTTP GET 方法。您可以在此处了解设计 RESTful api 的最佳实践:http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

    【讨论】:

      【解决方案6】:

      我生命中的 8 个小时永远不会回来......

      确保在 CorsConfiguration 中同时设置 Exposed Headers 和 Allowed Headers

      @Bean
      CorsConfigurationSource corsConfigurationSource() {
          CorsConfiguration configuration = new CorsConfiguration();
          configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
          configuration.setAllowedMethods(Arrays.asList("GET","POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
          configuration.setExposedHeaders(Arrays.asList("Authorization", "content-type"));
          configuration.setAllowedHeaders(Arrays.asList("Authorization", "content-type"));
          UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
          source.registerCorsConfiguration("/**", configuration);
          return source;
      }
      

      【讨论】:

        【解决方案7】:

        在很多地方,我看到需要添加此代码的答案:

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

        但在我的情况下,它会引发意外的类类型异常。 corsFilter() bean 需要 CorsFilter 类型,所以我已经完成了这些更改并将这个 bean 的定义放入我的配置中,现在一切正常。

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

        【讨论】:

          【解决方案8】:

          WebMvcConfigurerAdapter 类从 5.0 开始被弃用。WebMvcConfigurer 具有默认方法,无需此适配器即可直接实现。对于这种情况:

          @Configuration
          @EnableWebMvc
          public class WebMvcConfig implements WebMvcConfigurer {
              @Override
              public void addCorsMappings(CorsRegistry registry) {
                  registry.addMapping("/**").allowedOrigins("http://localhost:3000");
              }
          }
          

          另见:Same-Site flag for session cookie

          【讨论】:

            【解决方案9】:

            根据CORS filter documentation

            "Spring MVC 为 CORS 配置提供了细粒度的支持 通过控制器上的注释。然而 当与 Spring 一起使用时 安全建议依赖内置的 CorsFilter 在 Spring Security 的过滤器链之前订购”

            这样的事情将允许GET 访问/ajaxUri

            @Component
            @Order(Ordered.HIGHEST_PRECEDENCE)
            public class AjaxCorsFilter extends CorsFilter {
                public AjaxCorsFilter() {
                    super(configurationSource());
                }
            
                private static UrlBasedCorsConfigurationSource configurationSource() {
                    CorsConfiguration config = new CorsConfiguration();
            
                    // origins
                    config.addAllowedOrigin("*");
            
                    // when using ajax: withCredentials: true, we require exact origin match
                    config.setAllowCredentials(true);
            
                    // headers
                    config.addAllowedHeader("x-requested-with");
            
                    // methods
                    config.addAllowedMethod(HttpMethod.OPTIONS);
                    config.addAllowedMethod(HttpMethod.GET);
            
                    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
                    source.registerCorsConfiguration("/startAsyncAuthorize", config);
                    source.registerCorsConfiguration("/ajaxUri", config);
                    return source;
                }
            }
            

            当然,您的 SpringSecurity 配置必须允许使用列出的方法访问 URI。请参阅@Hendy Irawan 的回答。

            【讨论】:

              【解决方案10】:

              经过几个小时的研究,这个解决方案解锁了我:

              在配置中初始化 core() 选项

              @Override
              public void configure(HttpSecurity http) throws Exception {
              http
                  .cors()
                  .and()
                  .etc
              }
              

              根据您的意愿在 corsFilter 中初始化您的凭据、来源、标头和方法。

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

              我不需要使用这个类:

              @Bean
              public CorsConfigurationSource corsConfigurationSource() {
              }
              

              【讨论】:

                【解决方案11】:

                就我而言,我只是添加了这个类并使用@EnableAutConfiguration

                @Component
                public class SimpleCORSFilter extends GenericFilterBean {
                    /**
                     * The Logger for this class.
                     */
                    private final Logger logger = LoggerFactory.getLogger(this.getClass());
                
                    @Override
                    public void doFilter(ServletRequest req, ServletResponse resp,
                                         FilterChain chain) throws IOException, ServletException {
                        logger.info("> doFilter");
                
                        HttpServletResponse response = (HttpServletResponse) resp;
                        response.setHeader("Access-Control-Allow-Origin", "*");
                        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
                        response.setHeader("Access-Control-Max-Age", "3600");
                        response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
                        //response.setHeader("Access-Control-Allow-Credentials", "true");
                        chain.doFilter(req, resp);
                
                        logger.info("< doFilter");
                    }
                }
                

                【讨论】:

                  【解决方案12】:

                  使用 SpringBoot 2 Spring Security,下面的代码完美解决了 Cors 问题

                  @Bean
                  public CorsConfigurationSource corsConfigurationSource() {
                      CorsConfiguration configuration = new CorsConfiguration();
                      configuration.setAllowedOrigins(Collections.singletonList("*")); // <-- you may change "*"
                      configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH"));
                      configuration.setAllowCredentials(true);
                      configuration.setAllowedHeaders(Arrays.asList(
                              "Accept", "Origin", "Content-Type", "Depth", "User-Agent", "If-Modified-Since,",
                              "Cache-Control", "Authorization", "X-Req", "X-File-Size", "X-Requested-With", "X-File-Name"));
                      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
                      source.registerCorsConfiguration("/**", configuration);
                      return source;
                  }
                  
                  @Bean
                  public FilterRegistrationBean<CorsFilter> corsFilterRegistrationBean() {
                      FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(corsConfigurationSource()));
                      bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
                      return bean;
                  }
                  

                  然后对于网络安全配置,我添加了这个

                  @Override
                  protected void configure(HttpSecurity http) throws Exception {
                      http.headers().frameOptions().disable()
                              .and()
                              .authorizeRequests()
                              .antMatchers("/oauth/tokeen").permitAll()
                              .antMatchers(HttpMethod.GET, "/").permitAll()
                              .antMatchers(HttpMethod.POST, "/").permitAll()
                              .antMatchers(HttpMethod.PUT, "/").permitAll()
                              .antMatchers(HttpMethod.DELETE, "/**").permitAll()
                              .antMatchers(HttpMethod.OPTIONS, "*").permitAll()
                              .anyRequest().authenticated()
                              .and().cors().configurationSource(corsConfigurationSource());
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    若要在全球范围内启用 CORS,您需要在两个地方进行更改,如果您还使用 spring security with boot:

                    1.春季启动:

                    @Configuration
                    public class CorsConfiguration extends WebMvcConfigurationSupport {  
                        @Override
                        public void addCorsMappings(CorsRegistry registry) {
                            registry.addMapping("/**").allowedOrigins("*").allowedMethods("*")
                            .allowCredentials(true);
                        }
                    }
                    

                    你可以在WebMvcConfigurerAdapter中做同样的事情,或者创建WebMvcConfigurer的bean。

                    2。春季安全

                    @Override
                        protected void configure(HttpSecurity http) throws Exception {
                            http.cors().and()
                                    .authorizeRequests()
                                    .antMatchers(HttpMethod.OPTIONS).permitAll() //Permits your preflight request
                    }
                    

                    这会启用所有方法、所有路径和来源。因此,请谨慎使用,仅在开发中使用。 在 Spring Boot 2.3.3.RELEASE 上工作

                    【讨论】:

                      【解决方案14】:

                      我遇到了类似的问题,但具体要求是从我们的端点中的装饰器中设置 CORS 标头,如下所示:

                      @CrossOrigin(origins = "*", allowCredentials = "true")
                      @PostMapping(value = "/login")
                      

                      或者

                      @CrossOrigin(origins = "*")
                      @GetMapping(value = "/verificationState")
                      

                      因此,简单地拦截请求、手动设置 CORS 标头并返回 200 不是一种选择,因为在某些情况下需要允许 allowCredentials 为真,并且不允许使用通配符。当然,CORS 注册会有所帮助,但由于我们的客户在 android 和 iOS 上的电容器有角,因此没有特定的域可以注册。因此,在我看来,干净的做法是将预检直接通过管道传输到端点以让它们处理它。我用这个解决了它:

                      @Component
                      public class PreflightFilter extends OncePerRequestFilter {
                      
                          private static final Logger logger = LoggerFactory.getLogger(PreflightFilter.class);
                      
                          @Override
                          protected void doFilterInternal(HttpServletRequest request,
                                                          HttpServletResponse response, FilterChain chain)
                                  throws ServletException, IOException {
                      
                              if (CorsUtils.isPreFlightRequest(request)) {
                                  logger.info("Preflight request accepted");
                                  SecurityContextHolder.getContext().setAuthentication(createPreflightToken(request));
                              }
                              chain.doFilter(request, response);
                          }
                      
                          private UsernamePasswordAuthenticationToken createPreflightToken(HttpServletRequest request) {
                              UserDetails userDetails = new User("Preflight", "",
                                      true, true, true, true,
                                      Stream.of(new SimpleGrantedAuthority("AppUser")).collect(Collectors.toSet()));
                              UsernamePasswordAuthenticationToken preflightToken =
                                      new UsernamePasswordAuthenticationToken(
                                              userDetails, null, userDetails.getAuthorities());
                              preflightToken
                                      .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                              return preflightToken;
                          }
                      }
                      

                      请记住,端点装饰器在这里的工作方式并不像人们所期望的那样使用通配符!

                      【讨论】:

                        【解决方案15】:

                        这允许任何具有 CORS 凭据的来源:

                        @Component
                        public class FilterChainConfig implements Filter {
                            @Override
                            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                                if (servletResponse instanceof HttpServletResponse){
                                    HttpServletResponse response = (HttpServletResponse)servletResponse;
                                    HttpServletRequest request = (HttpServletRequest) servletRequest;
                                    String requestOrigin = request.getHeader("Origin");
                                    response.setHeader("Access-Control-Allow-Origin", requestOrigin);
                                    response.setHeader("Access-Control-Allow-Credentials", "true");
                                    //response.setHeader("Access-Control-Allow-Methods", "*");
                                    response.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, HEAD");
                                    response.setHeader("Access-Control-Max-Age", "3600");
                                    response.setHeader("Access-Control-Allow-Headers", "*");
                                    filterChain.doFilter(request, response);
                                }
                            }
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 2017-03-18
                          • 1970-01-01
                          • 2017-04-29
                          • 2015-09-04
                          相关资源
                          最近更新 更多