2016-11-17 100 views
0

我已经实现了具有用于登录/注销的REST通道的单面应用程序。我已经开始使用JWT,但我想转向基于会话的通信。我目前是春天的XML配置:由REST服务创建的弹簧安全令牌未保存在会话中

<http pattern="/spring/login" security="none" create-session="always" /> 
<http pattern="/spring/logout" security="none" create-session="never" /> 

<http pattern="/spring/**" entry-point-ref="restAuthenticationEntryPoint" 
    create-session="always"> 
    <csrf disabled="true" /> 
    <custom-filter before="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter" /> 
</http> 

现在,jwtAuthenticationFilter被修改,使得它不记录如果验证是否存在,如果不是,它是从头部解析:

@Override 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
     throws IOException, ServletException { 
    HttpServletRequest req = (HttpServletRequest) request; 
    HttpServletResponse res = (HttpServletResponse) response; 

    // skip if authorization already exists 
    Authentication sessionAuth = SecurityContextHolder.getContext().getAuthentication(); 
    if (sessionAuth != null) { 
     LOGGER.info("Already authenticated as {}", sessionAuth.getPrincipal()); 
     chain.doFilter(request, response); 
     return; 
    } 
    LOGGER.info("Try to authorize"); 

的/春天/ login方法创建令牌,并试图把它变成安全上下文:

SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS512), claimsSet); 
    try { 
     signedJWT.sign(signer); 
     String token = "Bearer " + signedJWT.serialize(); 
     response.setToken(token); 

     Authentication auth = authenticationManager.authenticate(new JWTToken(signedJWT)); 
     SecurityContextHolder.getContext().setAuthentication(auth);    
    } catch(JOSEException | ParseException e) { 

我期待什么,是该令牌将出现在接下来的安全上下文REST呼叫。但是,日志表明,通过下一个请求,令牌不在安全上下文中,它被创建并通过servlet过滤器放到那里,然后它就会出现在后续请求中。

我在这里做错了什么?我期望,如果我要求在/ spring/login调用上创建会话,Authentication放入SecurityContext也会在会话中保留。这显然不是这种情况。为了让Spring Security保留REST调用中存储的令牌,我需要做些什么?

回答

0

由于security="none",Spring安全上下文未保存到会话中。 Spring的安全过滤器并未针对该请求启动,其中包括将安全上下文保留到会话中的安全过滤器。

的解决方案是为登录/注销提供匿名身份验证:

<http request-matcher="regex" pattern="/spring/log(in|out)" create-session="ifRequired" entry-point-ref="restAuthenticationEntryPoint" > 
    <csrf disabled="true" /> 
    <custom-filter before="FIRST" ref="anonymousAuthFilter" /> 
</http> 

<beans:bean id="anonymousAuthFilter" 
    class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter"> 
    <beans:constructor-arg value="Anonymous"/> 
</beans:bean> 

我不是很高兴通过这种结构,因为它需要制造假身份验证,以便能够创造真实的,但我无法找到更好的东西。