Spring Boot 中的并发会话和 OAuth2 问题

问题描述 投票:0回答:2

我正在使用 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 调用。有什么建议吗?

java spring-boot spring-security oauth-2.0
2个回答
0
投票

当使用多个副本(实例)部署oauth应用程序并且会话存储在redis等中时,SessionRegistryImpl是不够的,使用SpringSessionBackedSessionRegistry它允许在集群环境中与Spring Security进行并发会话管理。

https://docs.spring.io/spring-session/docs/current/api/org/springframework/session/security/SpringSessionBackedSessionRegistry.html

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

0
投票

您应该在 RegisterSessionAuthenticationStrategy 进行调试以检查到底发生了什么

您使用单个帐户登录,但外部授权服务器对控制服务中的并发会话一无所知。它返回您两个不同的身份验证对象。

如果可能,尝试实现您自己的身份验证并覆盖 hashCode 和 equals

© www.soinside.com 2019 - 2024. All rights reserved.