用户只能单设备登录
有时候在同一个系统中,只允许一个用户在一个设备登录。
之前的登陆者被顶掉
将最大会话数设置为1就可以保证用户只能同时在一个设备上登录
java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
.anyRequest().authenticated() // 其他需要认证
.and()
.csrf().disable() // 关闭csrf跨站请求伪造防护
// 设置一个用户只能在一个设备上登录 设置最大会话数
.sessionManagement().maximumSessions(1)
;
}
不允许后来者登录
java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
.anyRequest().authenticated() // 其他需要认证
.and()
.csrf().disable() // 关闭csrf跨站请求伪造防护
// 设置一个用户只能在一个设备上登录 设置最大会话数
.sessionManagement().maximumSessions(1)
.maxSessionsPreventsLogin(true) // 禁止后来者登录
;
}
源码解读
ConcurrentSessionControlAuthenticationStrategy类
java
public void onAuthentication(Authentication authentication,
HttpServletRequest request, HttpServletResponse response) {
// 获取当前用户的所有session
final List<SessionInformation> sessions = sessionRegistry.getAllSessions(
authentication.getPrincipal(), false);
int sessionCount = sessions.size();
// 同时允许几个session存在
int allowedSessions = getMaximumSessionsForThisUser(authentication);
// 当前登录的数量小于允许的数量
if (sessionCount < allowedSessions) {
// They haven't got too many login sessions running at present
return;
}
// 不进行限制
if (allowedSessions == -1) {
// We permit unlimited logins
return;
}
// 已经达到允许数量了
if (sessionCount == allowedSessions) {
// 当前session 是否为null
HttpSession session = request.getSession(false);
if (session != null) { // 不为null则判断一下是否有与当前session同一个sessionId的
// Only permit it though if this request is associated with one of the
// already registered sessions
for (SessionInformation si : sessions) {
if (si.getSessionId().equals(session.getId())) {
return;
}
}
}
// If the session is null, a new one will be created by the parent class,
// exceeding the allowed number
}
// 这里说明session已超过限制数量了
allowableSessionsExceeded(sessions, allowedSessions, sessionRegistry);
}
protected void allowableSessionsExceeded(List<SessionInformation> sessions,
int allowableSessions, SessionRegistry registry)
throws SessionAuthenticationException {
// exceptionIfMaximumExceeded该值就是配置的maxSessionsPreventsLogin
if (exceptionIfMaximumExceeded || (sessions == null)) {
throw new SessionAuthenticationException(messages.getMessage(
"ConcurrentSessionControlAuthenticationStrategy.exceededAllowed",
new Object[] { Integer.valueOf(allowableSessions) },
"Maximum sessions of {0} for this principal exceeded"));
}
// Determine least recently used session, and mark it for invalidation
SessionInformation leastRecentlyUsed = null;
for (SessionInformation session : sessions) {
if ((leastRecentlyUsed == null)
|| session.getLastRequest()
.before(leastRecentlyUsed.getLastRequest())) {
leastRecentlyUsed = session;
}
}
leastRecentlyUsed.expireNow();
}