如何在 Spring webflux 应用程序中使用 Spring WebSessionIdResolver 和 Spring Security 5?
How to use Spring WebSessionIdResolver with Spring Security 5 in a Spring webflux application?
目前我正在体验新的 Spring 反应式堆栈,并想在 Spring Session 2.0.
中使用反应式功能
在传统的 Servlet 方法中,Spring Session 提供了一个 HttpSessionStrategy
来检测 cookie 或请求 header 中的 session。使用 HeaderHttpSessionStrategy
可以很容易地为 RESTful API 实现类似身份验证的令牌(默认情况下,他的名称是 X-AUTH-TOKEN
)。
Spring 5 核心提供了一个 WebSessionIdResolver
来为 Reactive 环境做同样的事情。
但是当它与 Spring 安全一起使用并希望它以传统方式工作时,我无法让它工作。
Session配置文件。
@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("/users/{user}/**").access(this::currentUserMatchesPath)
.anyExchange().authenticated()
.and()
.build();
}
一个测试 rest 控制器文件,它 returns 当前 Session 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 时,没有 session 信息响应 header。
curl -v -u "user:password" http://localhost:8080/sessionId
然后我在查询结果中获取了sessionid,放入请求headers中去访问受保护的资源,得到了401。
curl -v -X POST -H "X-SESSION-ID:xxxx" http://localhost:8080/posts
更新:可以找到工作样本here。
Spring 框架的 spring-web 模块默认使用基于 cookie 的 CookieWebSessionIdResolver。如果您创建一个类型为 HeaderWebSessionIdResolver 的替代 bean,它会被 Spring Session 自动选取并切换到 header-based 策略。
在任一策略中,它都适合读取传入的 ServerExchange headers,并查找 session id,无论是读取 Cookie header 还是 SESSION http header.
这些策略还会创建响应 headers,无论是 set-cookie 客户端(网络浏览器或您的代码)填充 Cookie 的指令,还是给您 SESSION header(HeaderWebSessionIdResolver 的header 名称的默认名称)。
目前我正在体验新的 Spring 反应式堆栈,并想在 Spring Session 2.0.
中使用反应式功能在传统的 Servlet 方法中,Spring Session 提供了一个 HttpSessionStrategy
来检测 cookie 或请求 header 中的 session。使用 HeaderHttpSessionStrategy
可以很容易地为 RESTful API 实现类似身份验证的令牌(默认情况下,他的名称是 X-AUTH-TOKEN
)。
Spring 5 核心提供了一个 WebSessionIdResolver
来为 Reactive 环境做同样的事情。
但是当它与 Spring 安全一起使用并希望它以传统方式工作时,我无法让它工作。
Session配置文件。
@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("/users/{user}/**").access(this::currentUserMatchesPath)
.anyExchange().authenticated()
.and()
.build();
}
一个测试 rest 控制器文件,它 returns 当前 Session 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 时,没有 session 信息响应 header。
curl -v -u "user:password" http://localhost:8080/sessionId
然后我在查询结果中获取了sessionid,放入请求headers中去访问受保护的资源,得到了401。
curl -v -X POST -H "X-SESSION-ID:xxxx" http://localhost:8080/posts
更新:可以找到工作样本here。
Spring 框架的 spring-web 模块默认使用基于 cookie 的 CookieWebSessionIdResolver。如果您创建一个类型为 HeaderWebSessionIdResolver 的替代 bean,它会被 Spring Session 自动选取并切换到 header-based 策略。
在任一策略中,它都适合读取传入的 ServerExchange headers,并查找 session id,无论是读取 Cookie header 还是 SESSION http header.
这些策略还会创建响应 headers,无论是 set-cookie 客户端(网络浏览器或您的代码)填充 Cookie 的指令,还是给您 SESSION header(HeaderWebSessionIdResolver 的header 名称的默认名称)。