zoukankan      html  css  js  c++  java
  • Session管理之超时设置和强制下线

    (一)Session超时时间设置的三种方式:

        (1)在web.xml中设置session-config

    <session-config>
      <session-timeout>2</session-timeout>
     </session-config>

        即交互间隔时间最长为2分钟(该处时间单位为分钟),2分钟后session.getAttribute()获取的值为空。

        (2)在Tomcat的/conf/web.xml中session-config,默认值为:30分钟

    <session-config>
         <session-timeout>30</session-timeout>
    </session-config>

       时间单位为分钟。

        (3)在Servlet中设置

    HttpSession session = request.getSession();
    session.setMaxInactiveInterval(60);

      该处时间单位为秒

      优先级:Servlet中设置 >web.xml设置 > Tomcat/conf/web.xml设置


    (二)同一用户强制下线

        大家都知道在目前很多的web项目中,大多数情况下都是可以让同一个用户账号在不同的登录入口登录的,但这样其实就显得不是很严谨了,毕竟信息修改等操作对于信息是否能完全即时同步还是个未知之数。所以,接下来,我要做的只是对于不同浏览器的同一个用户账号的强制下线处理,对于同一个浏览器暂不做考虑,先来看下面这张图。大概的了解一下:

        从上面可以看出:同一个浏览器对于不同的账号,登录时会产生相同的sessionId,这也就导致了用户之间信息的覆盖;不同浏览器对于不同的账号登录时,登录时会产生不同的sessionId,这也就给了我们可操作的空间了,正是要利用这一点来进行判断和相应处理。

        (1)添加监听器

        为了方便这里使用Session监控的方式,创建SessionListener,如下:

    public class SessionListener implements HttpSessionBindingListener{
    
        @Override
        public void valueBound(HttpSessionBindingEvent event){
            // TODO Auto-generated method stub
            
        }
        @Override
        public void valueUnbound(HttpSessionBindingEvent event){
            // TODO Auto-generated method stub
            
        }
    }

        这里HttpSessionBindingListener和HttpSessionListener效果一样,大家可以任选其一。重载两个方法:session的创建和销毁。

        当然,在web.xml中添加相应配置是必不可少的:

    <listener>
       <listener-class>com.yoki.util.SessionListener</listener-class>
    </listener>

        由于sessionId和userId需要存储,方便后面的判断,我们在上面的类中添加两个Map,如下:

    //保存username和session的映射
    public static HashMap<String,Session> MAP1 = new HashMap<String,Session>();
    //保存sessionID和username的映射
    public static HashMap MAP2 = new HashMap();

        最后,用户登录验证成功时需要调用一个方法来判断是否强制下线:

    public static void userLogin(Session session,String sUserName){
        //已登录
        if(MAP2.containsValue(sUserName)){
           Session l_session = MAP1.get(sUserName);
           //不同浏览器,同一用户(强制下线前一个)
           if(l_session != null && l_session.getId() != session.getId()){
              MAP1.remove(sUserName);
              MAP2.remove(l_session.getId());
              l_session.setAttribute("msg", "您的账号已在另一处登录!");
              MAP2.put(session.getId(), sUserName);
              MAP1.put(sUserName, session);
           }
           //同一浏览器,同一用户(不做任何变动)
           
        }else{
           //未登录
           if(MAP2.containsKey(session.getId())){
              //同一浏览器,不同用户(不做任何变动)
           }else{
              //不同浏览器,不同用户(正常添加)
              MAP2.put(session.getId(), sUserName);
              MAP1.put(sUserName, session);
           }
        }
    
    }

        解释一下:这里使用username和userId效果一样,看你们怎么方便怎么用了,方法中的逻辑是根据上面的图来编写的,首先判断用户是否登录了,因为MAP中保存了相关的session关联信息,所以可以通过这个来判断;由于此处只对不同浏览器相同用户进行处理,所以直接判断是否是同一个浏览器。方法的参数session是用户在当前浏览器登录时的信息,我们可以从MAP中得到之前保存过的相同用户的session信息,与之进行比较,里面的逻辑是:移除MAP中保存的之前的用户信息(对应的session此时未销毁),并给其session添加一个msg信息(后面用到,往下看),再添加新的用户信息。

        上面的方法调用放在登录验证成功后,各自项目不同,但登录验证的类基本差不多:

    SessionListener.userLogin(session, USERNAME);

        (2)添加前端页面调用的方法

        在登录验证的类中添加如下方法:

    /*
     * 判断用户是否重复登录
     */
    @RequestMapping(value="/checkUserOnline")
    @ResponseBody
    public void checkUserOnline(HttpServletRequest request,HttpServletResponse response) throws IOException{
        HttpSession session=request.getSession();  
        PrintWriter out = response.getWriter();
        String msg = "";
        if(session.getAttribute("msg") != null){
           msg = session.getAttribute("msg").toString();
           System.out.println(msg);
        }
        out.print(session.getAttribute("msg"));
    }

        方法中获取之前添加到session中的msg,用来判断是否强制下线,继续。

        (3)前端页面循环调用

        选择一个页面,最好是所有页面都用到的,比如我用的index.jsp,如下:

    <script type="text/javascript">
       $(document).ready(function(){
          setInterval("checkUserOnline()",5000); //每隔5秒判断一次
       }
       
       function checkUserOnline(){
          var msg = "";
          $.ajax({
            type : "POST",
            url : "checkUserOnline",
            data : {},
            async: false,
            success : function(data){
               msg = data;
            }
          });
          if (msg == 'null' || msg == '' || msg == 'undefined'){
             return;
          }else{
             //调用你的注销用户方法
             var url="<%=path%>/logout.do";
             $.get(url,function(data){});
          }
       }
    </script>

        js中调用setInterval方法,设置调用的方法和间隔时间,方法里通过ajax调用上面添加的类并返回msg,通过msg来判断是否调用注销方法(路径啥的自己注意,能调用到就ok)。

        (4)注销

        一般web项目登录进去后都会有个退出按钮,点击即返回到登录页,此时在里面添加一行代码,防止错误,可能会出现重新登录报session已被销毁的错误提示,但第二次便会成功,这里便是为了消除该错误:

    SessionListener.MAP2.remove(session.getId());

       参考:https://my.oschina.net/u/3747963/blog/1787633

  • 相关阅读:
    mybatis-plus-generator 实践
    Mybatis-Plus使用全解
    DevExpress v18.2新版亮点——DevExtreme篇(四)
    DevExpress VCL Controls 2019发展路线图(No.2)
    【版本更新】开发工具DevExtreme发布v18.2.7|附下载
    DevExpress v18.2新版亮点——DevExtreme篇(三)
    独家!DevExpress VCL Controls 2019发展路线图(No.1)
    界面控件DevExpress发布v18.2.7,新版全新出发|附下载
    DevExpress v18.2新版亮点——DevExtreme篇(二)
    DevExpress WinForms使用教程:皮肤颜色和LookAndFeel
  • 原文地址:https://www.cnblogs.com/rigid/p/8796976.html
Copyright © 2011-2022 走看看