应用程序上的 Spring 最大会话数,而不是应用程序上用户的最大会话数

Posted

技术标签:

【中文标题】应用程序上的 Spring 最大会话数,而不是应用程序上用户的最大会话数【英文标题】:Spring Max Sessions on Application, NOT Max Sessions for a User on an Application 【发布时间】:2016-08-11 21:37:18 【问题描述】:

我正在使用 jhipster 编写一个网络应用程序。它正在使用弹簧。我试图限制同一用户登录我的应用程序的次数,并让它在名为 ServerConfiguration.java 的文件上工作:

 @Override
protected void configure(HttpSecurity http) throws Exception 
    http
    .and()
        .formLogin()
        .loginProcessingUrl("/api/authentication")
        .successHandler(ajaxAuthenticationSuccessHandler)
        .failureHandler(ajaxAuthenticationFailureHandler)
        .usernameParameter("j_username")
        .passwordParameter("j_password")
        .permitAll()
    .
    .
    .
    .
    .and()            
        .sessionManagement()
        .maximumSessions(Integer.parseInt(env.getProperty("spring.maxuser.sessions")))
                 .maxSessionsPreventsLogin(true);
    


@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() 
    return new HttpSessionEventPublisher();

这使得特定用户只能多次登录我的应用程序。

现在,我的问题是如何使我的应用程序仅对x 数量的different 用户开放/可访问。例如,我希望我的应用程序只能被 200 个用户访问。而当用户 201 出现并想要登录时,它就无法登录。

我在另一篇帖子spring limit max sessions ; limit max users 上看到了一个答案,但我不知道该代码到底应该放在哪里。

public class MySessionAuthenticationStrategy extends ConcurrentSessionControlStrategy 
int MAX_USERS = 1000; // Whatever
SessionRegistry sr;

public MySessionAuthenticationStrategy(SessionRegistry sr) 
    super(sr);
    this.sr = sr;


@Override
public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) 
    if (sr.getAllPrincipals().size() > MAX_USERS) 
        throw new SessionAuthenticationException("Maximum number of users exceeded");
    
    super.onAuthentication(authentication, request, response);

我应该创建这个新类MySessionAuthenticationStrategy 以及如何从我的httpConfigure 类转到这个新类MySessionAuthenticationStrategy

非常感谢。

【问题讨论】:

【参考方案1】:

试试这个。 创建一个类来扩展默认会话注册表:

@Component
public class MySessionRegistry extends org.springframework.security.core.session.SessionRegistryImpl     

将您的配置方法更新为如下所示。

    @Autowired
    MySessionRegistry sessionRegistry; 
    void configure(HttpSecurity http) throws Exception 
        http.formLogin()
                .loginProcessingUrl("/api/authentication")
                .successHandler(ajaxAuthenticationSuccessHandler)
                .failureHandler(ajaxAuthenticationFailureHandler)
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .permitAll().and()
                .sessionManagement()
                .maximumSessions(Integer.parseInt(env.getProperty("spring.maxuser.sessions")))
                .sessionRegistry(sessionRegistry)
                .maxSessionsPreventsLogin(true);
    

然后在登录/验证过程中,试试这个:

    @Autowired
    MySessionRegistry sessionRegistry; 

    public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) 
        if (calculateMaxSessions(sessionRegistry) > MAX_USERS) 
            throw new SessionAuthenticationException("Maximum number of users exceeded");
         else 
            //Authenticate
        
    

    public int calculateMaxSessions(SessionRegistry sessionRegistry)
        final List<Object> principals = sessionRegistry.getAllPrincipals();
        if (principals != null) 
            List<SessionInformation> sessions = new ArrayList<>();
            for (Object principal : principals) 
                sessions.addAll(sessionRegistry.getAllSessions(principal, false));
            
            return sessions.size();
        
        return 0;
    

我希望这会有所帮助。干杯!

【讨论】:

非常感谢您的回复。 1- 所以我只需要创建这个空类 2- 然后在我的SecurityConfiguration.java calss 上添加我新创建的类的新实例。我不知道 Autowired 是如何工作的。然后添加这个新属性:sessionsRegistry(myNewlyCreatedClassInstance) 3- 我不知道我在哪里进行登录/身份验证.... :( 这是我第一次看这个春天的东西。我把这个放在哪里?再次感谢 【参考方案2】:

您可以在 WebSecurityConfig 类中添加它

@Override
    protected void configure(HttpSecurity http) throws Exception           
        http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .invalidSessionUrl("/")
            .maximumSessions(1)
            .maxSessionsPreventsLogin(true)
            .expiredUrl("/login?invalid-session=true");
    

并在您的 CustomUserDetails 类中覆盖 equals() 和 hash()

@Override
public boolean equals(Object o) 
    if (this == o) return true;
    if (!(o instanceof CustomUserDetails)) return false;
    CustomUserDetails that = (CustomUserDetails) o;
    return user.getUsername().equals(that.user.getUsername()) &&
            user.getEmailAddress().equals(that.user.getEmailAddress()) &&
            user.getPassword().equals(that.user.getPassword());


@Override
public int hashCode() 
    
    return Objects.hash(user.getUsername(), user.getEmailAddress(), user.getPassword());

【讨论】:

以上是关于应用程序上的 Spring 最大会话数,而不是应用程序上用户的最大会话数的主要内容,如果未能解决你的问题,请参考以下文章

Grails Spring Security 最大并发会话

Spring Security 注销和最大会话数

Shiro 中的并发会话控制

远程观看监控时电脑显示设备已达到最大网络连接数怎么解决?

每个用户的最大用户会话数 - apache shiro

AWS Elastic Beanstalk 上的 Java 应用程序会话超时