2014-10-05 100 views
1

我使用弹簧会话版本1.0.0.M1,我已将其配置为使用MapSessionRepository: sessionFilterChainReg.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST),假,dispatcherServletReg.getName());春季安全CSRF不带弹簧会议工作

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


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

,然后在网络配置:

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); 

现在的会话是空的,所以存储库返回空的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) 
+0

只有在准备好包含CSRF标记的视图之后,CSRF支持才会创建会话。你在哪里使用CSRF令牌?您需要一个包含CSRF令牌的视图(即JSP,Thymeleaf模板,响应头等)。另一个要尝试的是它在Spring Session中工作吗? – 2014-10-07 13:15:46

+0

嗨,罗布,我更新了这个问题。是的,如果没有Spring会话,它会很好地工作,并且CSRF令牌正确传递给过滤器,但会话在HttpSessionCsrfTokenRepository上返回:loadToken:66为null。 – 2014-10-07 13:20:52

+0

你可以看看请求,看看有什么饼干?它可能与https://github.com/spring-projects/spring-session/issues/34相关如果您看到多个会话cookie,则应删除所有这些cookie,然后重试。 – 2014-10-07 14:21:56

回答

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

解决了这个问题。