springSecurity学习之springSecurity用户单设备登录

用户只能单设备登录

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

之前的登陆者被顶掉

将最大会话数设置为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();
	}

https://zhhll.icu/2023/框架/springSecurity/6.用户只能单设备登录/

相关推荐
NE_STOP10 小时前
MyBatis-配置文件解读及MyBatis为何不用编写Mapper接口的实现类
java
后端AI实验室15 小时前
用AI写代码,我差点把漏洞发上线:血泪总结的10个教训
java·ai
程序员清风17 小时前
小红书二面:Spring Boot的单例模式是如何实现的?
java·后端·面试
belhomme17 小时前
(面试题)Redis实现 IP 维度滑动窗口限流实践
java·面试
Be_Better17 小时前
学会与虚拟机对话---ASM
java
开源之眼19 小时前
《github star 加星 Taimili.com 艾米莉 》为什么Java里面,Service 层不直接返回 Result 对象?
java·后端·github
Maori31620 小时前
放弃 SDKMAN!在 Garuda Linux + Fish 环境下的优雅 Java 管理指南
java
用户9083246027321 小时前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
小王和八蛋21 小时前
DecimalFormat 与 BigDecimal
java·后端
beata21 小时前
Java基础-16:Java内置锁的四种状态及其转换机制详解-从无锁到重量级锁的进化与优化指南
java·后端