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.用户只能单设备登录/

相关推荐
Lhappy嘻嘻5 小时前
Java IO|File 文件操作 + 字节流 / 字符流完整笔记 + 递归删除文件实战
java·笔记·php
伊玛目的门徒5 小时前
试用leetcode之典中典 二数之和问题
java·算法·leetcode
懒鸟一枚8 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
我命由我1234510 小时前
执行 Gradle 指令报错,无法将“grep”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
考虑考虑10 小时前
Sentinel安装
java·后端·微服务
凤凰院凶涛QAQ11 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
掘金_答案12 小时前
上线那天,一个 ConcurrentHashMap 差点送走我的 AI 客服——3 天排查 JVM 血泪史
java·后端·架构
猿与禅13 小时前
CosId 分布式 ID 生成器完全教程:从架构原理到生产落地
java·shardingsphere·雪花算法·分布式id·高性能·cosid·号段模式
MindUp13 小时前
企业网盘权限模型解析:多层级访问控制与审计能力选型指南
java·linux·运维
NG47713 小时前
【软件设计与体系结构】-策略设计模式
java·设计模式·软件工程