如何在Spring webflux应用程序中使用Spring WebSessionIdResolver和Spring Security 5?

如何在Spring webflux应用程序中使用Spring WebSessionIdResolver和Spring Security 5?

问题描述:

目前我遇到了新的Spring反应堆栈,并且希望在Spring Session 2.0中使用反应式功能。如何在Spring webflux应用程序中使用Spring WebSessionIdResolver和Spring Security 5?

在传统的Servlet方法中,Spring Session提供了一个HttpSessionStrategy来检测cookie或请求头中的会话。对于RESTful API,使用HeaderHttpSessionStrategy很容易实现令牌身份验证(默认情况下他的名字是X-AUTH-TOKEN)。

Spring 5 core提供了一个WebSessionIdResolver来为Reactive环境做同样的事情。

但是,当它与Spring Security一起使用,并希望它作为传统方式工作,我不能得到它的工作。

SessionConfig文件。

@EnableSpringWebSession 
public class SessionConfig { 

    @Bean 
    public ReactorSessionRepository sessionRepository() { 
     return new MapReactorSessionRepository(new ConcurrentHashMap<>()); 
    } 

    @Bean 
    public WebSessionIdResolver headerWebSessionIdResolver() { 
     HeaderWebSessionIdResolver resolver = new HeaderWebSessionIdResolver(); 
     resolver.setHeaderName("X-SESSION-ID"); 
     return resolver; 
    } 
} 

部分SecurityConfig。

@EnableWebFluxSecurity 
class SecurityConfig { 

    @Bean 
    SecurityWebFilterChain springWebFilterChain(HttpSecurity http) throws Exception { 
     return http 
      .authorizeExchange() 
      .pathMatchers(HttpMethod.GET, "/posts/**").permitAll() 
      .pathMatchers(HttpMethod.DELETE, "/posts/**").hasRole("ADMIN") 
      //.pathMatchers("https://*.com/users/{user}/**").access(this::currentUserMatchesPath) 
      .anyExchange().authenticated() 
      .and() 
      .build(); 
} 

测试休息控制器文件,它返回当前会话ID。

@RestController 
public class SessionRestController { 


    @GetMapping("/sessionId") 
    public Map<String, String> sessionId(WebSession session){ 
     Map<String, String> map = new HashMap<>(); 
     map.put("id", session.getId()); 
     return map ; 
    } 

} 

当我启动应用程序,并使用curl访问/的sessionId,没有会话信息的响应头。

curl -v -u "user:password" http://localhost:8080/sessionId 

而且我得到了在查询结果中的会话ID,并把它变成请求头访问受保护的资源,并得到了401

curl -v -X POST -H "X-SESSION-ID:xxxx" http://localhost:8080/posts 

更新:工作示例可以发现here

Spring框架的spring-web模块默认使用CookieWebSessionIdResolver,它基于cookie。如果您创建了一个HeaderWebSessionIdResolver类型的替代bean,它将在Spring会话中自动拾取并切换到基于标头的策略。

在任一策略中,它都适合读取传入的ServerExchange标头,并查找会话标识,无论是读取Cookie标头还是SESSION http标头。

这些策略还会创建响应标头,无论是为客户端(Web浏览器还是代码)填充Cookie的set-cookie指令,还是为您提供SESSION标头(HeaderWebSessionIdResolver标头名称的缺省名称) 。

+0

我清楚地知道这一点,并且已经阅读了关于'WebSessionIdResolver'的测试代码。但在我的示例中,它与Spring Session和Spring Security一起使用时无法按预期工作。我已经使用'curl'来测试我的API,会话信息没有附加到响应头中,也没有验证我在后面的步骤中从第一个请求获得的会话。 – Hantsy

+0

将我的代码更新到Spring Boot 2.0.0.M6并使其工作,请检查[示例代码](https://github.com/hantsy/spring-reactive-sample/tree/master/session-header)。 – Hantsy