我有一个集成了Spring Security的Reactive Application,它是由spring initilizer创建的,主要包含thre3软件包(spring boot,spring security和webflux)。
我正在尝试通过application.properties
中的以下配置来配置会话超时:
spring.session.timeout=1m
使用mvn spring-boot:run
启动应用程序后,http://localhost:8080
可以访问它,并要求我登录(默认为安全性设置)。我可以使用用户名user
和控制台上生成的密码登录。
根据我的配置,我希望在闲置1分钟之后,再次刷新页面http://localhost:8080
时,它可以要求我重新登录。但实际上直到30分钟后才出现
所以我怀疑上面的配置不起作用
我使用了错误的配置吗?
可以在以下位置找到复制存储库:https://github.com/ZhuBicen/ReactiveSpringSecurity.git
答案 0 :(得分:2)
Spring可能应该像在servlet中一样,为您的情况为反应式堆栈自动配置
。但是,“会话”是状态,除非有一些持久性存储支持它,否则该状态不会扩展。您可以对内存ReactiveSessionRepository
使用Spring Session抽象,即使您还没有Redis之类的后备存储。当您确实获得了适当的支持后备存储并添加了相应的依赖性时,可以删除内存中的ReactiveSessionRepository
,因为spring boot会为您自动配置ReactiveSessionRepository
。
首先,添加spring session依赖项
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
第二,手动创建ReactiveSessionRepository
bean。 (注意:如果您使用Redis而不是内存等,可以为您自动配置此功能。)
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.session.SessionProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.ReactiveMapSessionRepository;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
import java.util.concurrent.ConcurrentHashMap;
/**
* This ReactiveSessionRepository isn't auto-configured so we need to create it and manually set the timeout on it.
* Later, ReactiveRedisSessionRepository will be auto-configured so we can delete this
*/
// https://www.baeldung.com/spring-session-reactive#in-memory-configuration
@Configuration
@EnableSpringWebSession
@RequiredArgsConstructor // if lombok
@Slf4j // if lombok
public class SessionConfig {
private final SessionProperties sessionProperties;
@Bean
public ReactiveSessionRepository reactiveSessionRepository() {
ReactiveMapSessionRepository sessionRepository = new ReactiveMapSessionRepository(new ConcurrentHashMap<>());
int defaultMaxInactiveInterval = (int) sessionProperties.getTimeout().toSeconds();
sessionRepository.setDefaultMaxInactiveInterval(defaultMaxInactiveInterval);
log.info("Set in-memory session defaultMaxInactiveInterval to {} seconds.", defaultMaxInactiveInterval);
return sessionRepository;
}
}
第三,设置属性spring.session.timeout=3600
。
答案 1 :(得分:1)
我终于通过实现定制的ServerAuthenticationSuccessHandler
来解决它,例如:
class SuccessHandler extends RedirectServerAuthenticationSuccessHandler {
@Override
public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
// set to -1 means the session will never expired
// webFilterExchange.getExchange().getSession().subscribe(session->session.setMaxIdleTime(Duration.ofSeconds(-1)));
webFilterExchange.getExchange().getSession().subscribe(session->session.setMaxIdleTime(Duration.ofMinutes(60)));
return super.onAuthenticationSuccess(webFilterExchange, authentication);
}
}
可以通过类似的方式设置SuccessHandler:
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {
http.formLogin().authenticationSuccessHandler(new SuccessHandler());
return http.build();
}
}
答案 2 :(得分:0)
您配置的参数与网络浏览器的cookie会话无关。
该参数配置Spring Session
,这是通过标头提供会话来处理服务,REST API等会话的一种方式。
https://spring.io/projects/spring-session
会话cookie过去一直绑定到threadlocal中的线程,这在响应式应用程序中不起作用。因此,为了存储会话,您需要能够将会话存储在其他位置。 Redis是您可以在其中存储Web会话的一个示例。
这里是使用webflux,redis和spring session管理websession的教程。