首页 > 解决方案 > 将 spring-security 与 spring-webflux 一起使用时禁用 WebSession 创建

问题描述

我正在运行一个带有 rest api 的无状态 spring-boot 应用程序,并希望按照https://www.baeldung.com/spring-security-session的描述禁用 WebSessions 的创建

我创建了自己的不存储会话的 WebSessionManager。

   @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);
                   }
               });
           }
       };
   }

它有效,但我想知道是否有更好的方法来不创建会话。

标签: javaspring-securityspring-webflux

解决方案


问题 #6552:具有 Webflux 安全性的会话创建策略将由Spring 团队修复。

问题是每个请求都会调用请求缓存,以查看是否有保存的值要重播,因此正在为每个请求查找 WebSession。由于使用无效会话 ID 查找 WebSession,因此 Spring WebFlux 使 SESSION cookie 无效。~绞盘

我创建了 gh-7157 来限制何时访问请求缓存(以及 WebSession)。同时,如果您不需要请求缓存,可以使用以下方法禁用它:

http
.requestCache()
    .requestCache(NoOpServerRequestCache.getInstance());

您可以在问题 #7157 ServerRequestCacheWebFilter 中跟踪修补的进度,导致 WebSession 被读取每个请求

另外DarrenJiang1990建议更完整的解决方案:

.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();
    }
}

更多信息:API 的 Spring webflux 自定义身份验证


推荐阅读