美文网首页
一个账号

一个账号

作者: Spring_java | 来源:发表于2018-10-22 14:32 被阅读0次

最近有个新需求,要实现账户在一个浏览器A登录后,当账户再到第二个浏览器登录的时候,就会把第一个浏览器上的会话销毁,强制去登录。

实现原理

第一次登录

  • 1:在拦截器/过滤器中,获取用户输入的地址,如果是登录,就跳转到登录上,然后生成一个session。在这个session中保存一个key loginUser value就是这个用户的信息
  • 2:设置一个全局map。map中保存了这个用户的姓名(作为key)以及本次session的ID(作为value),在保存前,先判断这个map里面是否保存了相同的key,如果没有,就保存进去

第二次登录

  • 1:当第二次登录的时候,再生成一个session,全局map此时已经存在了同名的key了。根据本次登录的账户名,取出上一次同名的session。然后就简单的从map中移除掉,然后把最新的id添加进去

第一个强制登录

  • 1:当用户进行任何操作的时候,会被拦截器拦截,然后根据key
    loginUser 获取session中的用户信息,如果为空,可能是session过期了

如果不为空,那么就从session中获取同名的用户信息,假如本次的session ID和从全局map中保存的session ID不一样。就说明。当前的用户所具备的session id 已经被从全局map
中移除掉了,那么就重定向到登录页面上。

代码

  • 1:登录
    @PostMapping("/login")
    public String doLogin(HttpServletRequest request, HttpServletResponse response, Model model){

        String userName = request.getParameter("userName");
        String password = request.getParameter("password");


        System.out.println(userName+" : "+password);
        LoginUser user = userService.findUser(userName, password);


        model.addAttribute("name",userName);

        //使用过滤器来进行校验重复,有可能存在多个账号

        HttpSession currentSession = request.getSession();

        currentSession.setAttribute("loginUser",user);


        Map<String, String> sessionMap = SessionManager.getSessionMap();


        if(!sessionMap.containsKey(user.getUserName())){
            sessionMap.put(user.getUserName(),currentSession.getId());
            System.out.println(user.getUserName()+" 第一次登陆时的session ID是:" + currentSession.getId());

        }else{
            //同名用户上一次登录的时候
            String beforeSessionID = sessionMap.get(user.getUserName());
            if(sessionMap.containsKey(user.getUserName())  && !beforeSessionID.equals(currentSession.getId()) ){
                sessionMap.remove(user.getUserName());
                sessionMap.put(user.getUserName(),currentSession.getId());
          }
        }
        return "hello";
    }


  • 2: 拦截器
public class MyFilter implements Filter {

    private Set<String> excludeUrl = new HashSet<>(Arrays.asList("/login", "/loginOut","/css/**","/fonts/**","/js/**","/favicon.ico"));

    private String[] excludesPattern = new String[]{
            "/login",
            "/favicon.ico",
            "/css/**",
            "/fonts/**",
            "/js/**",
            "/loginOut",
            "/login*",
            "/org.apache*",
    };

    private PathMatcher pathMatcher=new AntPathMatcher();

    public  boolean uriIsExist(String uri){
        for(String path: excludesPattern){
            if(pathMatcher.match(path,uri)){
                return  true;
            }
        }
        return false;
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpSession currentSession = request.getSession();
        String requestURI = request.getRequestURI();
        if(uriIsExist(requestURI)){
            filterChain.doFilter(servletRequest,servletResponse);
            return;

        }
        LoginUser loginUser = (LoginUser) currentSession.getAttribute("loginUser");
        //如果user为空,可能是session过期,或者是被强制清空了。必须重新登录
        if (loginUser == null) {
            response.sendRedirect(request.getServletContext() + "/login");
        } else {
            Map<String, String> sessionMap = SessionManager.getSessionMap();
            //获取session中保存的用户名称。
            String userName = loginUser.getUserName();

            //获取已经存在的该用户所保存的sessionID.
            String beforeSessionID = sessionMap.get(userName);
            //如果现在登录成功的同名用户的sessionid和已经存在的id不一致,表示同样名字的session会话在后面产生了,又有一个人登录上来了。
            //本次sessionid已经是属于要被强制下线的session了。

            /**
             * 核心代码是在公用map中,如果存在同名用户,就删除上一次会话,保存新的会话。这个map里面一直保存最新的session ID
             */
            if (!currentSession.getId().equals(beforeSessionID)) {

               String requestPath= request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
               response.sendRedirect(requestPath + "/login");

            } else {
                //表示是最近登录上来的用户的操作。可以放行
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }

    }

    @Override
    public void destroy() {

    }
}





相关文章

  • 一个账号

    最近有个新需求,要实现账户在一个浏览器A登录后,当账户再到第二个浏览器登录的时候,就会把第一个浏览器上的会话销毁,...

  • 账号账号

    湖北5:2761649306江西1辽宁1广西3河南6重庆1黑龙江2/3上海4/5

  • 账号!账号!

    好久没在当当买书了,今天已登录不上去了——每次都告诉我账号或密码不对! 唉! 是自己记忆出错了么? 没有换过账号与...

  • [eos23]协议-账号和权限-part1

    1 概述 账号表示eosio区块链网络中的一个参与者。根据账号中的权限配置,账号可以是一个个体或者一个组织。 账号...

  • 哔哩哔哩-直播步骤

    直播的步骤: 一个正常的账号,账号申请调到若原有账号需要解绑,请参考手机账号更换。 账号注册& 直播的要求 以下为...

  • iOS 开发者账号之间的管理

    在开发的过程中,可能需要一个账号管理其他多个账号的情况;以下操作:使用账号A来管理账号B步骤: 一、登录账号B: ...

  • 轻问v2.3

    新增机构账号 什么是机构账号? 机构账号是轻问APP为线下签约的机构用户提供的一个特殊账号。 为什么要有机构账号?...

  • 账号验证 2020-12-19

    一个没有什么影响力的账号,是称不上什么账号的,只不过是一个用户基数的数字罢了。 我们注册的一些账号。一个账号想要成...

  • 本地设置多个git账号

    我们在日常开发中,有可能会有多个 git 账号,比如说工作一个账号,私人一个账号。对于多个账号我们可以使用配置 s...

  • Android Library 发布到 Jcenter 步骤

    [TOC] 创建 Jcenter 账号 提供官网注册账号地址:官网 注册账号,这里有一个容易忽略的坑:注册账号的时...

网友评论

      本文标题:一个账号

      本文链接:https://www.haomeiwen.com/subject/fthgzftx.html