I am running a stateless spring-boot application with a rest api and want to disable the creation of WebSessions as described https://www.baeldung.com/spring-security-session
I have created my own WebSessionManager that does not store the session.
@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);
}
});
}
};
}
It works but I wonder if there is a better way to not create a session.
The Issue #6552: Session Creation Policy with Webflux Security is going to be fixed by Spring team.
The problem is that the request cache is being invoked for every request to see if there is a value saved to replay and thus the WebSession is being looked up for every request. Since the WebSession is being looked up with an invalid session id, Spring WebFlux invalidates the SESSION cookie. ~ rwinch
I created gh-7157 to limit when the request cache is being accessed (and thus the WebSession). In the meantime if you don't need the request cache, you can disable it using:
http
.requestCache()
.requestCache(NoOpServerRequestCache.getInstance());
You can track the progress of patching in Issue #7157 ServerRequestCacheWebFilter causes WebSession to be read every request .
Additionally DarrenJiang1990 is suggesting more complete solution:
.and().securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
The security context in a WebFlux application is stored in a ServerSecurityContextRepository. Its WebSessionServerSecurityContextRepository implementation, which is used by default, stores the context in session. Configuring a NoOpServerSecurityContextRepository instead would make our application stateless
(Previous workaround)
Additionally to overriding WebSessionManager
you can disable all the security features and replace the authenticationManager
& securityContextRepository
with your custom implementations stripping out the session-based functionalities:
@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();
}
}
Further information: Spring webflux custom authentication for API .
I've disabled WebSessionManager by the following trick
@Bean
public WebSessionManager webSessionManager() {
// Emulate SessionCreationPolicy.STATELESS
return exchange -> Mono.empty();
}
All other solutions didn't help for me.
Use the: NoOpServerSecurityContextRepository intended for this purpose.
@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;
}
}
Did you try:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.