春季会议和CORS

时间:2015-02-11 03:00:38

标签: rest spring-mvc spring-security cors spring-session

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

  1. 如果我使用http代理的相对URI(将http://xxxx/api映射到客户端应用中的/ api),则效果很好。
  2. 如果我直接使用完整的URL,我在使用CORS时遇到问题,它无法获取会话信息,以下是Spring安全日志。
  3.     2015-02-11 10:46:57,745 [http-nio-8080-exec-29] DEBUG   org.springframework.security.web.FilterChainProxy - /api/mgt/appupdates at position 1 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
        2015-02-11 10:46:57,745 [http-nio-8080-exec-29] DEBUG org.springframework.security.web.FilterChainProxy - /api/mgt/appupdates at position 2 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
        2015-02-11 10:46:57,745 [http-nio-8080-exec-29] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - No HttpSession currently exists
        2015-02-11 10:46:57,745 [http-nio-8080-exec-29] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
    
    

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

    Spring会话配置:

     @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还有另一个初始化程序(@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只在没有OPTIONS方法中执行。此解决方案暂时克服了此障碍。我认为这可能是与Spring Session相关的错误。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

可以在请求方法帮助中添加@CrossOrigin吗?如下所示:

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


        return "";
    }