如何在 Spring webflux 应用程序中将 Spring WebSessionIdResolver 与 Spring Security 5 结合使用?

Han*_*tsy 6 spring spring-security reactive-programming spring-session spring-webflux

目前我正在体验新的 Spring 反应式堆栈,并希望在 Spring Session 2.0 中使用反应式功能。

在传统的 Servlet 方法中,Spring Session 提供了一个HttpSessionStrategy来检测 cookie 或请求标头中的会话。它很容易用于为 RESTful APIHeaderHttpSessionStrategy实现类似身份验证的令牌(默认名称为X-AUTH-TOKEN)。

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

但是当它与 Spring Security 一起使用并希望它以传统方式工作时,我无法让它工作。

会话配置文件。

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

部分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("/users/{user}/**").access(this::currentUserMatchesPath)
            .anyExchange().authenticated()
            .and()
            .build();
}
Run Code Online (Sandbox Code Playgroud)

一个测试剩余控制器文件,它返回当前的会话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 ;
    }

}
Run Code Online (Sandbox Code Playgroud)

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

curl -v -u "user:password" http://localhost:8080/sessionId
Run Code Online (Sandbox Code Playgroud)

我在查询结果中获取了会话id并将其放入请求标头中以访问受保护的资源,并得到401。

curl -v -X POST -H "X-SESSION-ID:xxxx" http://localhost:8080/posts
Run Code Online (Sandbox Code Playgroud)

更新:可以在此处找到工作示例。

gre*_*urn 2

Spring框架的spring-web模块默认使用它的CookieWebSessionIdResolver,它是基于cookie的。如果您创建 HeaderWebSessionIdResolver 类型的替代 bean,Spring Session 将自动选择它并切换到基于标头的策略。

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

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

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