0%

用户只能单设备登录

用户只能单设备登录

有时候在同一个系统中,只允许一个用户在一个设备登录。

之前的登陆者被顶掉

将最大会话数设置为1就可以保证用户只能同时在一个设备上登录

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
.anyRequest().authenticated() // 其他需要认证
.and()
.csrf().disable() // 关闭csrf跨站请求伪造防护
// 设置一个用户只能在一个设备上登录 设置最大会话数
.sessionManagement().maximumSessions(1)
;

}

不允许后来者登录

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
.anyRequest().authenticated() // 其他需要认证
.and()
.csrf().disable() // 关闭csrf跨站请求伪造防护
// 设置一个用户只能在一个设备上登录 设置最大会话数
.sessionManagement().maximumSessions(1)
.maxSessionsPreventsLogin(true) // 禁止后来者登录

;

}

源码解读

ConcurrentSessionControlAuthenticationStrategy类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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();
}

欢迎关注我的其它发布渠道