春季会议和 CORS

Posted

技术标签:

【中文标题】春季会议和 CORS【英文标题】:Spring Session and CORS 【发布时间】:2015-04-11 07:43:27 【问题描述】:

我正在为我的 REST API 使用 Spring session 和 Spring security,但是当我通过一个简单的过滤器启用 CORS 时遇到了问题。

    如果我通过 http 代理使用相对 URI(在客户端应用程序中将 http://xxxx/api 映射到 /api),效果很好。 如果我直接使用完整的URL,我在使用CORS的时候遇到了一个问题,它无法获取会话信息,下面是Spring安全日志。
2015-02-11 10:46:57,745 [http-nio-8080-exec-29] 调试 org.springframework.security.web.FilterChainProxy - /api/mgt/appupdates 在附加过滤器链中的第 10 个位置;触发过滤器:'WebAsyncManagerIntegrationFilter' 2015-02-11 10:46:57,745 [http-nio-8080-exec-29] 调试 org.springframework.security.web.FilterChainProxy - /api/mgt/appupdates 位于附加过滤器链中第 10 位的第 2 位;触发过滤器:'SecurityContextPersistenceFilter' 2015-02-11 10:46:57,745 [http-nio-8080-exec-29] 调试 org.springframework.security.web.context.HttpSessionSecurityContextRepository - 当前不存在 HttpSession 2015-02-11 10:46:57,745 [http-nio-8080-exec-29] 调试 org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession 没有可用的 SecurityContext:null。将创建一个新的。

我正在使用 Spring 堆栈,包括 Spring 4.1.4.RELEASE、Spring Security 4、Spring Session 1.0.0.RELEASE 等

春季会话配置:

 @Configuration
 @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60 * 120 )
 public class RedisHttpSessionConfig 

    @Bean 
    public HttpSessionStrategy httpSessionStrategy()
        return new HeaderHttpSessionStrategy(); 
    

   

Http Session 初始化类内容:

@Order(100)
public class RedisHttpSessionApplicationInitializer 
        extends AbstractHttpSessionApplicationInitializer 

RedisHttpSessionConfig 已加载到我的 Web 初始化程序 (@Order(0)) 中。还有另一个 Spring Security 的 Initializer(@Order(200))。

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer 

    private static final Logger log = LoggerFactory.getLogger(SecurityInitializer.class);

    @Override
    protected void beforeSpringSecurityFilterChain(ServletContext servletContext) 

        FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", DelegatingFilterProxy.class);
        corsFilter.addMappingForUrlPatterns(
                EnumSet.of(
                        DispatcherType.ERROR,
                        DispatcherType.REQUEST,
                        DispatcherType.FORWARD,
                        DispatcherType.INCLUDE,
                        DispatcherType.ASYNC),
                false,
                "/*"
        );

我已经解决了问题。我将 doFilter 方法移到了 else 块中。

@Named("corsFilter")
public class SimpleCorsFilter extends OncePerRequestFilter 

    private static final Logger log = LoggerFactory.getLogger(SimpleCorsFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
            throws ServletException, IOException 
        if (log.isDebugEnabled()) 
            log.debug("call doFilter in SimpleCORSFilter @");
        

        response.setHeader("Access-Control-Allow-Origin", "*");
 //       response.addHeader("X-FRAME-OPTIONS", "SAMEORIGIN");

        if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) 

            if (log.isDebugEnabled()) 
                log.debug("do pre flight...");
            

            response.setHeader("Access-Control-Allow-Methods", "POST,GET,HEAD,OPTIONS,PUT,DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Content-Type,Accept,x-auth-token,x-xsrf-token,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Access-Control-Allow-Origin");
            //response.setHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin,x-auth-token");
         else 
            filterChain.doFilter(request, response);
        
    


因此 doFilter 只在 none OPTIONS 方法中执行。 这个解决方案暂时克服了这个障碍。我认为这可能是与 Spring Session 相关的错误。

【问题讨论】:

您可能希望添加有关忽略 CROS 的过滤器。默认情况下它会阻止。你能确定你点击了过滤器吗? 【参考方案1】:

CORS filter 需要了解允许的请求标头列表中的 Spring Session 标头。 HeaderHttpSessionStrategy 将其定义为“x-auth-token”,但可以更改。请注意,任何以“x-”开头的标头都被视为特定于应用程序,这是您需要配置 CORS 过滤器以允许它的标志。

【讨论】:

我知道这个tomcat内置的CORSFilter,之前也用过其他自定义的CORS Filter和Intercepter。一切正常。这可能是 Spring Session 特定的问题。我已经解决了这个问题。 不仅允许,而且暴露。否则 Web 客户端将不会访问此标头。下面是 WebMvcConfigurer#addCorsMappings 的示例:registry.addMapping("/**").allowedOrigins("asterisk_here").allowedMethods("asterisk_here").allowedHeaders("X-Auth-Token").exposedHeaders ("X-Auth-Token");【参考方案2】:

它可以在您的请求方法帮助中添加@CrossOrigin 吗?如下:

@GetMapping("/path")
    @CrossOrigin
    public String detail(@PathVariable("id") Integer activityId)


        return "";
    

【讨论】:

以上是关于春季会议和 CORS的主要内容,如果未能解决你的问题,请参考以下文章

国际级敏捷方法权威会议Global Scrum Gathering 9月重磅亮相上海!把握最后机会,立即抢订稀缺名额!

春季网关请求被 CORS 阻止(无访问控制-允许-来源标头)

春季启动CORS配置

腾讯会议怎么使用

Spring安全和角度

CORS过滤器在春季不起作用