session 之session混乱解决方法(转)

简介: 知道了session混乱产生的原因之后,也就知道了问题的根源。同时也引出了很多的问题: 1、如何记录住在线人员(这里只有帐号的系统用户,不包括访客); 2、如何限制同一个帐号在同一时间段内只能够登陆一次系统? 3、如何限制不同的用户在同一台机器上登陆系统? 4、管理员如何踢人? 我们首先来分析上面的问题: 首先在服务器端当用户通过身份验证成功登陆系统之后,我们将此用户的信息记录住(OnLineUserManager.java),包括帐号、登陆日期、机器的IP地址、session的ID,session对象。

知道了session混乱产生的原因之后,也就知道了问题的根源。同时也引出了很多的问题:

1、如何记录住在线人员(这里只有帐号的系统用户,不包括访客);

2、如何限制同一个帐号在同一时间段内只能够登陆一次系统?

3、如何限制不同的用户在同一台机器上登陆系统?

4、管理员如何踢人?

我们首先来分析上面的问题:

首先在服务器端当用户通过身份验证成功登陆系统之后,我们将此用户的信息记录住(OnLineUserManager.java),包括帐号、登陆日期、机器的IP地址、session的IDsession对象。(记住session的ID极其重要,因为服务器识别session是根据id,只要id相同,服务器就认为是同一个用户);

(上面解决了问题1)

这样当用户登陆系统的时候我们首先根据帐号判断用户是否登陆了,如果已经登陆,提示用户;(这样就解决了问题2)

如果未登陆,判断用户的session的id是否已经在用户的信息OnLineUserManager里面了,如果是提示用户

关闭当前窗口,重新点击IE打开一个新的浏览器窗口。(这样session就不会混乱了)。

如果要限制不同的用户在同一台机器上登陆系统?这个就要根据IP地址来判断了。如果OnLineUserManager中

有通过这个机器登陆系统的用户,那么就提示用户同一台机器只能够一个帐号登陆;

(问题3也就解决了,注意:如果用户使用了代理服务器,那么此方法失效。这个方法适用于管理规范的用户,客户在局域网内使用,每个客户有固定的ip。

问题4如何踢人?你想想OnLineUserManager中记录了用户session对象,只要根据用户的帐号找到对应的

session对象,然后session.invalidate();这样就可以彻底的将捣乱的人提出系统了。

 

===============需要注意的是OnLineUserManager必须是线程安全的=我的实现如下==============

[java]  view plain copy
 
  1. package com.work.qxgl.login;  
  2.   
  3.   
  4.   
  5. import java.util.Vector;  
  6.   
  7.   
  8.   
  9. import org.apache.commons.logging.Log;  
  10.   
  11. import org.apache.commons.logging.LogFactory;  
  12.   
  13.   
  14.   
  15. import com.work.util.DateUtil;  
  16.   
  17.   
  18.   
  19. /** 
  20.  
  21.  * 统计在线用户数。前提是登录的时候限制一个用户只能够在系统中登录一次。 有了这个功能,管理员就可以管理在线用户,如果谁不服从管理,就可以从系统中踢出去。 
  22.  
  23.  * TODO 将jsp放到WEB-INF后面,然后所有的URL必须通过struts的action调用。 使用拦截器Interceptor来实现权限的控制! 
  24.  
  25.  * 或者通过web中的Filter来实现权限控制! 实现权限管理系统日志的记录! 
  26.  
  27.  *  
  28.  
  29.  * @author wangmingjie 
  30.  
  31.  *  
  32.  
  33.  */  
  34.   
  35. public class OnLineUserManager {  
  36.   
  37.     private static Log log = LogFactory.getLog(OnLineUserManager.class);  
  38.   
  39.     private Vector<OnLineUser> users = null;  
  40.   
  41.   
  42.   
  43.   
  44.   
  45.     private OnLineUserManager() {  
  46.   
  47.         users = new Vector<OnLineUser>();//在构造函数中初始化  
  48.   
  49.     }  
  50.   
  51.       
  52.   
  53.     static class SingletonHolder {  
  54.   
  55.         static OnLineUserManager instance = new OnLineUserManager();  
  56.   
  57.     }  
  58.   
  59.   
  60.   
  61.     /** 
  62.  
  63.      * 单例模式。这样简单而且能够保证线程安全。 
  64.  
  65.      *  
  66.  
  67.      * @return 
  68.  
  69.      */  
  70.   
  71.     public static OnLineUserManager getInstance() {  
  72.   
  73.         return SingletonHolder.instance;  
  74.   
  75.     }  
  76.   
  77.   
  78.   
  79.     /** 
  80.  
  81.      * 获取到登录用户的数量。 
  82.  
  83.      *  
  84.  
  85.      * @return 
  86.  
  87.      */  
  88.   
  89.     public synchronized int getCount() {  
  90.   
  91.         users.trimToSize();  
  92.   
  93.         return users.capacity();  
  94.   
  95.     }  
  96.   
  97.   
  98.   
  99.     /** 
  100.  
  101.      * 通过用户帐号判断该用户是否存在! 必须保证是线程安全的。 
  102.  
  103.      *  
  104.  
  105.      * @param userAccount 
  106.  
  107.      * @return 
  108.  
  109.      */  
  110.   
  111.     public synchronized boolean existUser(String userAccount) {  
  112.   
  113.         users.trimToSize();  
  114.   
  115.         boolean existUser = false;  
  116.   
  117.         for (int i = 0; i < users.capacity(); i++) {  
  118.   
  119.             if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {  
  120.   
  121.                 existUser = true;  
  122.   
  123.                 break;  
  124.   
  125.             }  
  126.   
  127.         }  
  128.   
  129.         return existUser;  
  130.   
  131.     }  
  132.   
  133.       
  134.   
  135.     /** 
  136.  
  137.      * @param sessionid 
  138.  
  139.      * @return 
  140.  
  141.      */  
  142.   
  143.     public synchronized boolean existSession(String sessionid) {  
  144.   
  145.         users.trimToSize();  
  146.   
  147.         boolean existUser = false;  
  148.   
  149.         for (int i = 0; i < users.capacity(); i++) {  
  150.   
  151.             if (sessionid.equals(((OnLineUser) users.get(i)).getSessionId())) {  
  152.   
  153.                 existUser = true;  
  154.   
  155.                 break;  
  156.   
  157.             }  
  158.   
  159.         }  
  160.   
  161.         return existUser;  
  162.   
  163.     }  
  164.   
  165.       
  166.   
  167.   
  168.   
  169.     /** 
  170.  
  171.      * 删除用户 
  172.  
  173.      *  
  174.  
  175.      * @param userAccount 
  176.  
  177.      * @return 
  178.  
  179.      */  
  180.   
  181.     public synchronized boolean deleteUser(String userAccount) {  
  182.   
  183.         users.trimToSize();  
  184.   
  185.         if (existUser(userAccount)) {  
  186.   
  187.             int currUserIndex = -1;  
  188.   
  189.             for (int i = 0; i < users.capacity(); i++) {  
  190.   
  191.                 if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {  
  192.   
  193.                     currUserIndex = i;  
  194.   
  195.                     break;  
  196.   
  197.                 }  
  198.   
  199.             }  
  200.   
  201.             if (currUserIndex != -1) {  
  202.   
  203.                 users.remove(currUserIndex);  
  204.   
  205.                 users.trimToSize();  
  206.   
  207.                 log.debug("用户" + userAccount + "退出系统"  
  208.   
  209.                         + DateUtil.getCurrentDateTime());  
  210.   
  211.                 log.debug("在线用户数为:" + getCount());  
  212.   
  213.                 return true;  
  214.   
  215.             }  
  216.   
  217.         }  
  218.   
  219.         return false;  
  220.   
  221.     }  
  222.   
  223.       
  224.   
  225.     /** 
  226.  
  227.      * 根据用户帐号,获取在线用户信息 
  228.  
  229.      * @param userAccount 
  230.  
  231.      * @return 
  232.  
  233.      */  
  234.   
  235.     public synchronized OnLineUser getUser(String userAccount) {  
  236.   
  237.         users.trimToSize();  
  238.   
  239.         if (existUser(userAccount)) {  
  240.   
  241.             int currUserIndex = -1;  
  242.   
  243.             for (int i = 0; i < users.capacity(); i++) {  
  244.   
  245.                 if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {  
  246.   
  247.                     currUserIndex = i;  
  248.   
  249.                     break;  
  250.   
  251.                 }  
  252.   
  253.             }  
  254.   
  255.             if (currUserIndex != -1) {  
  256.   
  257.                 return  users.get(currUserIndex);  
  258.   
  259.             }  
  260.   
  261.         }  
  262.   
  263.         return null;  
  264.   
  265.     }  
  266.   
  267.   
  268.   
  269.     /** 
  270.  
  271.      * 获取到在线用户的信息。 
  272.  
  273.      *  
  274.  
  275.      * @return 
  276.  
  277.      */  
  278.   
  279.     public synchronized Vector<OnLineUser> getOnLineUser() {  
  280.   
  281.         return users;  
  282.   
  283.     }  
  284.   
  285.   
  286.   
  287.     public synchronized void addUser(OnLineUser onLineUser) {  
  288.   
  289.         users.trimToSize();  
  290.   
  291.         if (!existUser(onLineUser.getUserAccount())) {  
  292.   
  293.             users.add(onLineUser);  
  294.   
  295.             log.debug(onLineUser.getUserAccount() + "/t登录到系统/t" + DateUtil.getCurrentDateTime());  
  296.   
  297.             // 通过request才能够获取到用户的ip等信息  
  298.   
  299.         } else {  
  300.   
  301.             log.debug(onLineUser.getUserAccount() + "已经存在");  
  302.   
  303.         }  
  304.   
  305.         log.debug("在线用户数为:" + getCount());  
  306.   
  307.     }  
  308.   
  309.   
  310.   
  311. }  

 

 

 ==================OnLineUser.java============================

[java]  view plain copy
 
  1. package com.work.qxgl.login;  
  2.   
  3.   
  4.   
  5. import java.io.Serializable;  
  6.   
  7.   
  8.   
  9. import javax.servlet.http.HttpSession;  
  10.   
  11.   
  12.   
  13. /** 
  14.  
  15.  * @author wangmingjie 
  16.  
  17.  * @date 2008-6-30下午04:56:37 
  18.  
  19.  */  
  20.   
  21. public class OnLineUser implements Serializable {  
  22.   
  23.   
  24.   
  25.     /** 
  26.  
  27.      *  
  28.  
  29.      */  
  30.   
  31.     private static final long serialVersionUID = 5461473880667036331L;  
  32.   
  33.       
  34.   
  35.     private String userId; //用户id  
  36.   
  37.     private String userAccount; //用户帐号  
  38.   
  39.     private String userName; //用户名称   
  40.   
  41.       
  42.   
  43.     private String loginTime; //登陆时间戳  
  44.   
  45.       
  46.   
  47.     private String sessionId; //session的ID  
  48.   
  49.     private String userIp ;//ip地址  
  50.   
  51.       
  52.   
  53.     private HttpSession session; //记住session对象,测试能否用来将人员踢出系统  
  54.   
  55.       
  56.   
  57.   
  58.   
  59.     public String getUserId() {  
  60.   
  61.         return userId;  
  62.   
  63.     }  
  64.   
  65.   
  66.   
  67.     public void setUserId(String userId) {  
  68.   
  69.         this.userId = userId;  
  70.   
  71.     }  
  72.   
  73.   
  74.   
  75.     public String getUserAccount() {  
  76.   
  77.         return userAccount;  
  78.   
  79.     }  
  80.   
  81.   
  82.   
  83.     public void setUserAccount(String userAccount) {  
  84.   
  85.         this.userAccount = userAccount;  
  86.   
  87.     }  
  88.   
  89.   
  90.   
  91.     public String getUserName() {  
  92.   
  93.         return userName;  
  94.   
  95.     }  
  96.   
  97.   
  98.   
  99.     public void setUserName(String userName) {  
  100.   
  101.         this.userName = userName;  
  102.   
  103.     }  
  104.   
  105.   
  106.   
  107.     public String getSessionId() {  
  108.   
  109.         return sessionId;  
  110.   
  111.     }  
  112.   
  113.   
  114.   
  115.     public void setSessionId(String sessionId) {  
  116.   
  117.         this.sessionId = sessionId;  
  118.   
  119.     }  
  120.   
  121.   
  122.   
  123.     public String getUserIp() {  
  124.   
  125.         return userIp;  
  126.   
  127.     }  
  128.   
  129.   
  130.   
  131.     public void setUserIp(String userIp) {  
  132.   
  133.         this.userIp = userIp;  
  134.   
  135.     }  
  136.   
  137.   
  138.   
  139.     public HttpSession getSession() {  
  140.   
  141.         return session;  
  142.   
  143.     }  
  144.   
  145.   
  146.   
  147.     public void setSession(HttpSession session) {  
  148.   
  149.         this.session = session;  
  150.   
  151.     }  
  152.   
  153.   
  154.   
  155.     public String getLoginTime() {  
  156.   
  157.         return loginTime;  
  158.   
  159.     }  
  160.   
  161.   
  162.   
  163.     public void setLoginTime(String loginTime) {  
  164.   
  165.         this.loginTime = loginTime;  
  166.   
  167.     }  
  168.   
  169.     public String toString(){  
  170.   
  171.         return  "OnLineUser{userId="+userId+",userAccount="+userAccount  
  172.   
  173.         +",userName"+userName+",loginTime="+loginTime+",userIp="+userIp+",sessionId="+sessionId+"}";  
  174.   
  175.     }  
  176.   
  177.       
  178.   
  179.     //===============下面的数据只有在系统登陆日期中记录==================================  
  180.   
  181. //  private String logoutTime;//退出时间戳;  
  182.   
  183. //  private String logoutType;//退出方式 “session超时退出”;“1主动退出”  
  184.   
  185. //  private String lastAccessedTime;// 最后访问时间  
  186.   
  187.   
  188.   
  189. }  
目录
相关文章
|
7月前
|
存储 前端开发 机器人
09_Session案例
09_Session案例
52 4
Session的工作机制
Session的工作机制
88 0
|
XML NoSQL Java
SpringSession的源码解析(生成session,保存session,写入cookie全流程分析)
上一篇文章主要介绍了如何使用SpringSession,其实SpringSession的使用并不是很难,无非就是引入依赖,加下配置。但是,这仅仅只是知其然,要知其所以然,我们还是需要深入源码去理解。
698 0
SpringSession的源码解析(生成session,保存session,写入cookie全流程分析)
|
JSON 小程序 安全
关于session_key安全问题的解决方法
这是一个关于 session_key 安全问题的通知,简单的解释一下,这个 session_key 是一个会话的密钥,用于保证小程序和服务器之间的内容传输的安全,例如当你想获取到用户的某些开放数据时,必须使用这个 session_key 对传输的内容进行校验和解密。
695 0
|
存储 编解码 应用服务中间件
【JavaWeb】会话跟踪技术Cookie与Session原始真解(下)
文章目录 1 什么是会话? 2 Cookie技术 2.1 Cookie简介 2.2 Cookie的理解与创建 2.3 服务器获取Cookie与Cookie的修改 2.4 Cookie的生命控制与生命周期 2.5 Cookie有效路径Path设置 3 Session会话技术 3.1 初探Session 3.2 Session的创建、获取与基本使用 3.3 Session的生命控制与生命周期 3.4 如何理解Session底层是基于Cookie实现的?
【JavaWeb】会话跟踪技术Cookie与Session原始真解(下)
|
存储 应用服务中间件 数据安全/隐私保护
【JavaWeb】会话跟踪技术Cookie与Session原始真解(上)
文章目录 1 什么是会话? 2 Cookie技术 2.1 Cookie简介 2.2 Cookie的理解与创建 2.3 服务器获取Cookie与Cookie的修改 2.4 Cookie的生命控制与生命周期 2.5 Cookie有效路径Path设置 3 Session会话技术 3.1 初探Session 3.2 Session的创建、获取与基本使用 3.3 Session的生命控制与生命周期 3.4 如何理解Session底层是基于Cookie实现的?
【JavaWeb】会话跟踪技术Cookie与Session原始真解(上)
|
存储 安全 Java
会话怎么可以少了session和cookie
会话怎么可以少了session和cookie
会话怎么可以少了session和cookie
|
存储 开发框架 .NET
Cookie和Session的作用,区别和各自的应用范围,Session工作原理
Cookie和Session的作用,区别和各自的应用范围,Session工作原理
313 0