我正在使用 Spring Security 5.6.0 和 OAuth 2.0 身份验证。我试图将每个用户的并发会话限制为一个。经过一番尝试,我成功编写了这段代码:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
[...]
.sessionManagement()
.sessionFixation().migrateSession()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/expired")
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());
与
@Bean
public SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
但是,由于某种原因,这不起作用,让两个不同的浏览器使用同一用户登录进行 API 调用。有什么建议吗?
当使用多个副本(实例)部署oauth应用程序并且会话存储在redis等中时,SessionRegistryImpl是不够的,使用SpringSessionBackedSessionRegistry它允许在集群环境中与Spring Security进行并发会话管理。
@Inject
@Named("redisConnectionFactory")
private RedisConnectionFactory redisConnectionFactory;
@SuppressWarnings({ "unchecked" })
@Bean
public SessionRegistry sessionRegistry()
{
return new SpringSessionBackedSessionRegistry(new RedisIndexedSessionRepository(sessionRedisOperations()));
}
@Bean
public RedisOperations<Object, Object> sessionRedisOperations()
{
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Override
public void configure(HttpSecurity http) throws Exception
{
http
.sessionManagement()
.maximumSessions(maximumSessions)
.expiredUrl(("/login?ex=MultiSession"))
.sessionRegistry(sessionRegistry())
....
}
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800, redisFlushMode = RedisFlushMode.IMMEDIATE)
public class RedisConfig
{
@Bean
public RedisConnectionFactory redisConnectionFactory()
{
LettuceClientConfiguration clientConfig = getLettuceClientConfiguration();
....
}
}
您应该在 RegisterSessionAuthenticationStrategy 进行调试以检查到底发生了什么
您使用单个帐户登录,但外部授权服务器对控制服务中的并发会话一无所知。它返回您两个不同的身份验证对象。
如果可能,尝试实现您自己的身份验证并覆盖 hashCode 和 equals。