我能知道是否可以使用Spring Security来限制同时登录网站的最大用户数吗?
当然可以,但需要使用“concurrent-session-control”参数。例如,如果您希望最多只允许1000个用户同时登录,则可以进行相应的配置。如果超过这个数目,则会重定向到提示页面,说明已经超出了最大用户数。
我能知道是否可以使用Spring Security来限制同时登录网站的最大用户数吗?
当然可以,但需要使用“concurrent-session-control”参数。例如,如果您希望最多只允许1000个用户同时登录,则可以进行相应的配置。如果超过这个数目,则会重定向到提示页面,说明已经超出了最大用户数。
您可以通过访问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);
}
}
按照Spring Security参考手册中的描述,您需要将其注入到安全命名空间中。
在Spring Security 2.0中,会话控制的实现略有不同,您需要自定义ConcurrentSessionController。
我没有足够的声望来添加评论。但是getAllPrincipals返回所有主体,包括过期会话中的主体。使用以下方法之一来获取所有活动会话。
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();
}
这篇文章有点旧,但我在Spring Security 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>
会话认证策略引用
<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>
会话注册表
@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.");
}
我这样做是因为我基于安全性进行身份验证:自定义过滤器