2015-02-11 86 views
2

我爲我的REST API使用Spring會話和Spring安全性,但是當我通過一個簡單的過濾器啓用CORS時遇到了問題。春季會議和CORS

  1. 如果我通過http代理使用相對URI(地圖http://xxxx/api到客戶端應用程序中的/ api),它運行良好。
  2. 如果我直接使用了完整的URL,在使用CORS時遇到了問題,它無法獲取會話信息,以下是Spring安全日誌。
 
    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 4.1.4.RELEASE,春季安全4,春季會議1.0.0.RELEASE等

春季會議配置:

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

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

} 

HTTP會話初始化類內容:

@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方法轉換爲其他塊。

@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方法中執行。這個解決方案暫時克服了這個障礙。我認爲這可能是一個春季會議相關的錯誤。

+0

您可能希望添加一個關於忽略CROS的過濾器。默認情況下它會阻塞。你能確保你打過濾器嗎? – 2015-02-13 08:56:46

回答

0

A CORS filter需要了解允許的請求頭列表中的Spring Session頭。 HeaderHttpSessionStrategy將其定義爲「x-auth-token」,但可以更改。請注意,任何以「x-」開頭的標題都被視爲特定於應用程序,這是一個您需要配置您的CORS過濾器以允許它的告警標誌。

+0

我知道這個tomcat內置CORSFilter,並且還使用過其他自定義CORS過濾器和Intercepter。一切正常。這可能是Spring會話特定的問題。我已經解決了這個問題。 – Hantsy 2015-03-20 01:52:01

0

是否可以將@CrossOrigin添加到您的請求方法幫助中?如下所示:

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


     return ""; 
    }