Java 将spring security与spring webflux一起使用时禁用WebSession创建
我正在运行一个带有RESTAPI的无状态spring引导应用程序,并希望禁用WebSessions的创建,如前所述 我创建了自己的WebSessionManager,它不存储会话Java 将spring security与spring webflux一起使用时禁用WebSession创建,java,spring-security,spring-webflux,Java,Spring Security,Spring Webflux,我正在运行一个带有RESTAPI的无状态spring引导应用程序,并希望禁用WebSessions的创建,如前所述 我创建了自己的WebSessionManager,它不存储会话 @Bean public WebSessionManager webSessionManager() { return new WebSessionManager() { @Override @NonNull public Mo
@Bean
public WebSessionManager webSessionManager() {
return new WebSessionManager() {
@Override
@NonNull
public Mono<WebSession> getSession(@NonNull final ServerWebExchange exchange) {
return Mono.just(new WebSession() {
@Override
@NonNull
public String getId() {
return "";
}
@Override
@NonNull
public Map<String, Object> getAttributes() {
return new HashMap<>();
}
@Override
public void start() {
}
@Override
public boolean isStarted() {
return true;
}
@Override
@NonNull
public Mono<Void> changeSessionId() {
return Mono.empty();
}
@Override
@NonNull
public Mono<Void> invalidate() {
return Mono.empty();
}
@Override
@NonNull
public Mono<Void> save() {
return Mono.empty();
}
@Override
public boolean isExpired() {
return false;
}
@Override
@NonNull
public Instant getCreationTime() {
return Instant.now();
}
@Override
@NonNull
public Instant getLastAccessTime() {
return Instant.now();
}
@Override
public void setMaxIdleTime(@NonNull final Duration maxIdleTime) {
}
@Override
@NonNull
public Duration getMaxIdleTime() {
return Duration.ofMinutes(1);
}
});
}
};
}
它可以工作,但我想知道是否有更好的方法不创建会话。您尝试过:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
?这个问题将由Spring团队解决
问题在于,每个请求都会调用请求缓存,以查看是否保存了要重播的值,因此每个请求都会查找WebSession。由于正在使用无效会话id查找WebSession,因此Spring WebFlux会使会话cookie无效
我创建了gh-7157来限制何时访问请求缓存,从而限制WebSession。同时,如果您不需要请求缓存,可以使用以下方法禁用它:
您可以在中跟踪修补的进度
此外,还建议更完整的解决方案:
.and().securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
WebFlux应用程序中的安全上下文存储在ServerSecurityContextRepository中。默认情况下使用的WebSessionServerSecurityContextRepository实现将上下文存储在会话中。相反,配置NoOpServerSecurityContextRepository将使应用程序无状态
以前的解决方法
除覆盖WebSessionManager外,您还可以禁用所有安全功能,并使用您的自定义实现替换authenticationManager&securityContextRepository,去掉基于会话的功能:
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
// Disable default security.
http.httpBasic().disable();
http.formLogin().disable();
http.csrf().disable();
http.logout().disable();
// Add custom security.
http.authenticationManager(this.authenticationManager);
http.securityContextRepository(this.securityContextRepository);
// Disable authentication for `/auth/**` routes.
http.authorizeExchange().pathMatchers("/auth/**").permitAll();
http.authorizeExchange().anyExchange().authenticated();
return http.build();
}
}
更多信息:.使用用于此目的的:NoOpServerSecurityContextRepository
@Configuration
@EnableWebFluxSecurity
@ComponentScan(value = {"my.package.security"})
public class SpringSecurityConfig2 {
@Autowired private MyHeaderExchangeMatcher myHeaderExchangeMatcher;
@Autowired private MyReactiveAuthenticationManager myReactiveAuthenticationManager;
@Autowired private MyTokenAuthenticationConverter myTokenAuthenticationConverter;
@Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
http.httpBasic().disable().formLogin().disable().csrf().disable().logout().disable();
http...
.addFilterAt(webFilter(), SecurityWebFiltersOrder.AUTHORIZATION)
...;
return http.build();
}
@Bean
public AuthenticationWebFilter webFilter() {
AuthenticationWebFilter authenticationWebFilter =
new AuthenticationWebFilter(myReactiveAuthenticationManager);
authenticationWebFilter.setServerAuthenticationConverter(myTokenAuthenticationConverter);
authenticationWebFilter.setRequiresAuthenticationMatcher(myHeaderExchangeMatcher);
// NoOpServerSecurityContextRepository is used to for stateless sessions so no session or state is persisted between requests.
// The client must send the Authorization header with every request.
NoOpServerSecurityContextRepository sessionConfig = NoOpServerSecurityContextRepository.getInstance();
authenticationWebFilter.setSecurityContextRepository(sessionConfig);
return authenticationWebFilter;
}
}
我通过以下技巧禁用了WebSessionManager
@Bean
public WebSessionManager webSessionManager() {
// Emulate SessionCreationPolicy.STATELESS
return exchange -> Mono.empty();
}
所有其他解决方案对我都没有帮助。此应用程序使用的是spring webflux,因此我们没有HttpSecurity,而是ServerHttpSecurity,因此它不起作用。糟糕的是,我打开了多个项目,我确信这是有效的解决方案!我和SpringWebFlux的家伙们有点来往,他们有很多关于处理和安全的正在进行的项目…谢谢你的回复!虽然SecurityWebFilterChain无法解决创建Web会话的问题。我已经就Github问题就这个问题发表了评论,希望他们能很快将.sessionCreationPolicySessionCreationPolicy.STATELESS修补到WebFlux中。Spring团队正在修复这个问题。我已经用建议的解决方法更新了答案。
@Bean
public WebSessionManager webSessionManager() {
// Emulate SessionCreationPolicy.STATELESS
return exchange -> Mono.empty();
}