使用application作用域实现:当用户重复登录时,挤掉原来的用户

使用application作用域实现:当用户重复登录时,挤掉原来的用户

一、实现思想

1.application(ServletContext)是保存在服务器端的作用域,我们在application中保存两种形式的键值对:1:<userId, sessionId>,2:<sessionId, session>

2.每当一个用户登录时(将生成一个新的session),首先根据userId在application中查询sessionId:

如果没有查询到sessionId,说明还没有用户登录此账号,那么将<userId, sessionId>和<sessionId, session>两个数据保存到application中

  如果查询到了sessionId,说明已经有用户登录了,那么将执行以下3个步骤:

    1)先拿到已经登录的那个session,使其失效

    2)再将原来的session从application中删除,将新的session保存到application中(<sessionId, session>)

    3)最后将原来的sessionId从application中删除,将新的sessionId保存到application(<userId, sessionId>)

二、实现登录功能的handler的编码

@RequestMapping("/login")
    public String login(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) throws Exception{    
        String userName = request.getParameter("userName");
        String password = request.getParameter("password");
        HttpSession session = request.getSession();
        ServletContext application = session.getServletContext();   //获取application
        
        User user = new User(userName, password);
        User currentUser = userService.login(user);
        if (currentUser == null) {
            request.setAttribute("error", "用户名或密码错误");
            return "login";
        }
        
        String userId = String.valueOf(currentUser.getId());   //获取userId
        map.put("currentUser", currentUser);   //将user保存到session中,注意要使用@SessionAttributes注释
        if(application.getAttribute("userId") == null){  //说明还没有用户登录
            application.setAttribute(userId, session.getId());    //将sessionId保存到application
            application.setAttribute(session.getId(), session);   //将session保存到application
        }else{   //说明已经有用户登录
            String sessionId = (String) application.getAttribute(userId);   //根据userId获取上一个用户的sessionId
            HttpSession oldSession = (HttpSession) application.getAttribute(sessionId);   //根据sessionId获取上一个用户的session
            oldSession.invalidate();   //使oldSession失效
            application.removeAttribute(oldSession.getId());   //将oldSession从application中移除
            application.setAttribute(session.getId(), session);   //将新的session保存到application
            application.removeAttribute(userId);   //将oldSession的id从application中移除
            application.setAttribute(userId, session.getId());   //将新的session的Id保存到application
        }
        return "main";
    }

三、总结

1.请注意为什么要特意使用<userId, sessionId>将sessionId保存起来?

因为,当第二个用户登录时,我们要使第一个用户的session失效,就必须要拿到第一个用户的sessionId,所以我们需要将sessionId通过<userId, sessionId>的形式保存起来,才能通过userId找到第一个用户的sessionId,从而找到第一个用户的session,使其失效

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码匠的流水账

聊聊spring security oauth2的password方式的认证

本文主要来聊聊spring security oauth2的password方式的认证

41120
来自专栏码匠的流水账

spring security设置login的ajax返回

11220
来自专栏个人分享

单点登录的实现

从第三方系统单点登录到目标系统,第三方系统会发送token进行验证,通过解析token,获取相应的用户信息的json串。将其set到自己系统的session中。

40140
来自专栏码匠的流水账

SwitchUserFilter源码解析

spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/...

13210
来自专栏JavaEdge

Spring Security源码分析之SecurityContextPersistenceFilter

29380
来自专栏码匠的流水账

聊聊spring security的账户锁定

对于登录功能来说,为了防止暴力破解密码,一般会对登录失败次数进行限定,在一定时间窗口超过一定次数,则锁定账户,来确保系统安全。本文主要讲述一下spring se...

31820
来自专栏程序猿DD

Spring Security入门(二):基于数据库验证

前文导读:Spring-Security-入门(一):登录与退出 本文说明 本文是 spring security 与 mybatis 的整合,实现基于数据库...

1.2K70
来自专栏JadePeng的技术博客

Spring Security 架构与源码分析

Spring Security 主要实现了Authentication(认证,解决who are you? ) 和 Access Control(访问控制,也就...

15100
来自专栏个人分享

单点登录filter根据redis中的key判断是否退出

其实可以直接用userSession 但由于项目已经封装了,所以再创建个UserMessage实体类,在登录后将token存入session,当从redis中通...

23630
来自专栏JavaEdge

Spring Security权限框架理论与实战(二)-常用权限拦截器1 SecurityContextPersistenceFilter

通过观察Filter的名字,就能大概猜出来这个过滤器的作用,持久化SecurityContext实例 org.springframework.security...

23120

扫码关注云+社区

领取腾讯云代金券