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

相关推荐
m0_587383006 小时前
外卖CPS系统开发实战:从架构设计到运营落地全指南
java·spring·小程序·架构·需求分析
zhangzeyuaaa6 小时前
Python asyncio 事件循环演进:从手动管理到现代化实践
java·服务器·python
学编程就要猛6 小时前
流式编程及Spring中SSE实现
java·后端·spring·流式编程
随遇而安zx7 小时前
【多线程】---ConcurrentHashMap 源码解析
java·多线程·并发
不才不才不不才7 小时前
Spring 源码系列(27): @Transactional 七大失效场景与源码归因
java·后端·spring
随遇而安zx7 小时前
【多线程】---线程池 ThreadPoolExecutor 原理与调优
java·线程池·多线程
抠脚小弟7 小时前
WebSocketServer 使用详解:从入门到实战
java·spring·websocketserver
随便做点啥7 小时前
32卡64G-910B4-16后端集群部署报告
java·大数据·运维
Wang's Blog7 小时前
Java框架快速入门: Spring Security+OAuth2之字段验证与自定义验证注解实战
java·算法·spring
CodeStats7 小时前
【Java 类加载器】Java 类加载器完整体系深度拆解(上):从 JVM 启动到双亲委派模型
java·开发语言·jvm·classloader·双亲委派