Spring安全性csrf无法使用spring-session

时间:2014-10-05 06:35:28

标签: spring-security spring-session

我正在使用spring-session版本1.0.0.M1,我已将其配置为使用MapSessionRepository:         sessionFilterChainReg.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST),false,dispatcherServletReg.getName());

@Bean(name = {"defaultSessionFilter", "sessionFilter"})
public SessionRepositoryFilter sessionFilter() {
    return new SessionRepositoryFilter((SessionRepository) applicationContext.getBean("sessionRepository"));
}


@Bean(name = { "defaultSessionRepository", "sessionRepository" })
public SessionRepository defaultSessionRepository() {
    return new MapSessionRepository();
}

然后在web-config中:

    final FilterRegistration sessionFilterChainReg = servletContext.addFilter("sessionFilter", DelegatingFilterProxy.class);

所以我在register.jsp中有以下输入隐藏元素:

<input type="hidden" id="${_csrf.parameterName}" name="${_csrf.parameterName}" value="${_csrf.token}"/>

我可以看到页面使用正确的CSRF令牌呈现。当我提交POST请求时,CSRF过滤器被触发,令牌被正确传递给过滤器,过滤器调用HttpSessionCsrfTokenRepository:loadToken并在第66行我们看到:

HttpSession session = request.getSession(false);

现在会话为null,因此存储库返回一个空的CSRF令牌,然后抛出MissingCsrfTokenException。还有其他我需要配置的东西吗?

这是第66行的堆栈跟踪(还有更多,但我想这是它的相关部分):

at org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.loadToken(HttpSessionCsrfTokenRepository.java:66)
  at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:75)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
  at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
  at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
  at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:144)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
  at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
  at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
  at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
  at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
  at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1632)
  at org.springframework.session.web.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:83)
  at org.springframework.session.web.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:66)
  at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
  at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
  at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1632)

1 个答案:

答案 0 :(得分:1)

发现问题 - 我自己有一个Filter包裹HttpServletRequest对象,过滤器在SessionRepositoryFilter之前触发。我不确定这是正确的,但是在SessionRepositoryFilter我这样做之后强迫它发射:

@Bean(name = {"defaultSessionFilter", "sessionFilter"})
public Filter sessionFilter() {
    CompositeFilter compositeFilter = new CompositeFilter();
    compositeFilter.setFilters(Arrays.asList(new SessionRepositoryFilter((SessionRepository) applicationContext.getBean("sessionRepository")), applicationContext.getBean("myFilter")));

    return compositeFilter;
}

解决了这个问题。