2010-01-21 94 views
4

我可能知道使用spring security可以限制同时登录到网站的最大用户数吗?春天限制最大会话;限制最大用户数

明确地说,不是并发会话控制参数。我想要的是例如,我想限制最大只允许1000个用户同时登录。如果超过该转发通知页面,则说明超出最大用户数

回答

7

您可以通过访问SessionRegistry来查找当前有多少用户登录,从而使用Spring Security的并发会话控制。在Spring Security 3中,ConcurrentSessionControlStrategy负责控制是否允许用户在登录后创建一个会话您可以根据用户的数量扩展这个类并添加额外的检查。

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); 
    } 
} 

the Spring Security reference manual描述你会再注入到安全命名空间这个。

在Spring Security 2.0中,并发会话控制实现方式稍有不同,您可以改为自定义ConcurrentSessionController。

+5

有关getAllPrincipals的一点是,它也会从过期会话中返回主体。我发现自己必须通过sr.getAllSessions()来检查所有会话,以检查是否不计算已过期的会话。我的max_users更小,过期的会话没有被清除得足够快。 – mut1na 2012-02-20 14:50:47

1

我没有足够的知名度来添加评论。但getAllPrincipals会返回所有主体,包括过期会话中的主体。使用下面的一些方法getAllActiveSessions。

private List<SessionInformation> getActiveSessions(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; 
    } 
    return Collections.emptyList(); 
} 
0

这篇文章有点老,但我在春季安全4.1中遇到了同样的问题,我已经解决了这个问题。

会话管理

<security:http disable-url-rewriting="true" use-expressions="true" auto-config="true"> 
    <security:session-management invalid-session-url="/app/login" session-authentication-strategy-ref="sessionAuthenticationStrategy">         
    </security:session-management> 
</security:http> 

会话的认证策略-REF

<bean id="sessionAuthenticationStrategy" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy"> 
<constructor-arg> 
    <list> 
     <bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy"> 
      <constructor-arg ref="sessionRegistry"/> 
      <property name="maximumSessions" value="1" /> 
      <property name="exceptionIfMaximumExceeded" value="true" /> 
     </bean> 
     <bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"> 
     </bean> 
     <bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy"> 
      <constructor-arg ref="sessionRegistry"/> 
     </bean> 
    </list> 
</constructor-arg> 
</bean> 

的SessionRegistry

@Autowired 
private SessionRegistry sessionRegistry; 

认证

List<SessionInformation> sessions = new ArrayList<>(); 
for (Object principal : sessionRegistry.getAllPrincipals()) { 
    sessions.addAll(sessionRegistry.getAllSessions(principal, false)); 
} 
LOGGER.info("Sessiones Activas: " + sessions.size()); 
// filtro para limite de sessiones 
if (sessions.size() < max_sessions) { 
//authentication 
} else { 
    throw new SessionAuthenticationException("Maximo numero de Usuarios exedido."); 
} 

以这种方式,因为我基于安全进行身份验证:自定义筛选器