session 之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 plaincopy

  1. package com.work.qxgl.login;
  2. import java.util.Vector;
  3. import org.apache.commons.logging.Log;
  4. import org.apache.commons.logging.LogFactory;
  5. import com.work.util.DateUtil;
  6. /**
  7. * 统计在线用户数。前提是登录的时候限制一个用户只能够在系统中登录一次。 有了这个功能,管理员就可以管理在线用户,如果谁不服从管理,就可以从系统中踢出去。
  8. * TODO 将jsp放到WEB-INF后面,然后所有的URL必须通过struts的action调用。 使用拦截器Interceptor来实现权限的控制!
  9. * 或者通过web中的Filter来实现权限控制! 实现权限管理系统日志的记录!
  10. *
  11. * @author wangmingjie
  12. *
  13. */
  14. public class OnLineUserManager {
  15. private static Log log = LogFactory.getLog(OnLineUserManager.class);
  16. private Vector<OnLineUser> users = null;
  17. private OnLineUserManager() {
  18. users = new Vector<OnLineUser>();//在构造函数中初始化
  19. }
  20. static class SingletonHolder {
  21. static OnLineUserManager instance = new OnLineUserManager();
  22. }
  23. /**
  24. * 单例模式。这样简单而且能够保证线程安全。
  25. *
  26. * @return
  27. */
  28. public static OnLineUserManager getInstance() {
  29. return SingletonHolder.instance;
  30. }
  31. /**
  32. * 获取到登录用户的数量。
  33. *
  34. * @return
  35. */
  36. public synchronized int getCount() {
  37. users.trimToSize();
  38. return users.capacity();
  39. }
  40. /**
  41. * 通过用户帐号判断该用户是否存在! 必须保证是线程安全的。
  42. *
  43. * @param userAccount
  44. * @return
  45. */
  46. public synchronized boolean existUser(String userAccount) {
  47. users.trimToSize();
  48. boolean existUser = false;
  49. for (int i = 0; i < users.capacity(); i++) {
  50. if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {
  51. existUser = true;
  52. break;
  53. }
  54. }
  55. return existUser;
  56. }
  57. /**
  58. * @param sessionid
  59. * @return
  60. */
  61. public synchronized boolean existSession(String sessionid) {
  62. users.trimToSize();
  63. boolean existUser = false;
  64. for (int i = 0; i < users.capacity(); i++) {
  65. if (sessionid.equals(((OnLineUser) users.get(i)).getSessionId())) {
  66. existUser = true;
  67. break;
  68. }
  69. }
  70. return existUser;
  71. }
  72. /**
  73. * 删除用户
  74. *
  75. * @param userAccount
  76. * @return
  77. */
  78. public synchronized boolean deleteUser(String userAccount) {
  79. users.trimToSize();
  80. if (existUser(userAccount)) {
  81. int currUserIndex = -1;
  82. for (int i = 0; i < users.capacity(); i++) {
  83. if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {
  84. currUserIndex = i;
  85. break;
  86. }
  87. }
  88. if (currUserIndex != -1) {
  89. users.remove(currUserIndex);
  90. users.trimToSize();
  91. log.debug("用户" + userAccount + "退出系统"
  92. + DateUtil.getCurrentDateTime());
  93. log.debug("在线用户数为:" + getCount());
  94. return true;
  95. }
  96. }
  97. return false;
  98. }
  99. /**
  100. * 根据用户帐号,获取在线用户信息
  101. * @param userAccount
  102. * @return
  103. */
  104. public synchronized OnLineUser getUser(String userAccount) {
  105. users.trimToSize();
  106. if (existUser(userAccount)) {
  107. int currUserIndex = -1;
  108. for (int i = 0; i < users.capacity(); i++) {
  109. if (userAccount.equals(((OnLineUser) users.get(i)).getUserAccount())) {
  110. currUserIndex = i;
  111. break;
  112. }
  113. }
  114. if (currUserIndex != -1) {
  115. return  users.get(currUserIndex);
  116. }
  117. }
  118. return null;
  119. }
  120. /**
  121. * 获取到在线用户的信息。
  122. *
  123. * @return
  124. */
  125. public synchronized Vector<OnLineUser> getOnLineUser() {
  126. return users;
  127. }
  128. public synchronized void addUser(OnLineUser onLineUser) {
  129. users.trimToSize();
  130. if (!existUser(onLineUser.getUserAccount())) {
  131. users.add(onLineUser);
  132. log.debug(onLineUser.getUserAccount() + "/t登录到系统/t" + DateUtil.getCurrentDateTime());
  133. // 通过request才能够获取到用户的ip等信息
  134. } else {
  135. log.debug(onLineUser.getUserAccount() + "已经存在");
  136. }
  137. log.debug("在线用户数为:" + getCount());
  138. }
  139. }

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

[java] view plaincopy

  1. package com.work.qxgl.login;
  2. import java.io.Serializable;
  3. import javax.servlet.http.HttpSession;
  4. /**
  5. * @author wangmingjie
  6. * @date 2008-6-30下午04:56:37
  7. */
  8. public class OnLineUser implements Serializable {
  9. /**
  10. *
  11. */
  12. private static final long serialVersionUID = 5461473880667036331L;
  13. private String userId; //用户id
  14. private String userAccount; //用户帐号
  15. private String userName; //用户名称
  16. private String loginTime; //登陆时间戳
  17. private String sessionId; //session的ID
  18. private String userIp ;//ip地址
  19. private HttpSession session; //记住session对象,测试能否用来将人员踢出系统
  20. public String getUserId() {
  21. return userId;
  22. }
  23. public void setUserId(String userId) {
  24. this.userId = userId;
  25. }
  26. public String getUserAccount() {
  27. return userAccount;
  28. }
  29. public void setUserAccount(String userAccount) {
  30. this.userAccount = userAccount;
  31. }
  32. public String getUserName() {
  33. return userName;
  34. }
  35. public void setUserName(String userName) {
  36. this.userName = userName;
  37. }
  38. public String getSessionId() {
  39. return sessionId;
  40. }
  41. public void setSessionId(String sessionId) {
  42. this.sessionId = sessionId;
  43. }
  44. public String getUserIp() {
  45. return userIp;
  46. }
  47. public void setUserIp(String userIp) {
  48. this.userIp = userIp;
  49. }
  50. public HttpSession getSession() {
  51. return session;
  52. }
  53. public void setSession(HttpSession session) {
  54. this.session = session;
  55. }
  56. public String getLoginTime() {
  57. return loginTime;
  58. }
  59. public void setLoginTime(String loginTime) {
  60. this.loginTime = loginTime;
  61. }
  62. public String toString(){
  63. return  "OnLineUser{userId="+userId+",userAccount="+userAccount
  64. +",userName"+userName+",loginTime="+loginTime+",userIp="+userIp+",sessionId="+sessionId+"}";
  65. }
  66. //===============下面的数据只有在系统登陆日期中记录==================================
  67. //  private String logoutTime;//退出时间戳;
  68. //  private String logoutType;//退出方式 “session超时退出”;“1主动退出”
  69. //  private String lastAccessedTime;// 最后访问时间
  70. }
时间: 2024-07-30 13:51:43

session 之session混乱解决方法(转)的相关文章

hibernate中一种导致a different object with the same identifier value was already associated with the session错误方式及解决方法

先将自己出现错误的全部代码都贴出来: hibernate.cfg.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-con

Recycleview checkbox 复用出现混乱解决方法

今天在做项目的一个我的收藏页面时要实现这么一个效果: 每个item 前面都有一个checkbox ,主要布局是recycleview .当我们选中某项时,继续往下滑动下面某个的checkbox也会变成选中状态. 解决方法一比较暴力 viewHolder.setIsRecyclable(false); 这样viewholder就不进行复用,也不存在checkbox 混乱选中的问题了,但是 你滑动的时候卡的要死. 第二种就是在获取到的bean中设置一个标志位,但是需要修改bean .虽然只是加个字段

Response.Redirect(&quot;x.aspx);跳转后session为null的解决方法

通常我们做登陆的时候都是登录成功后为管理员保存一些信息,一般都会写类似下面的代码 if(登录成功) { Session["xx"] = "user"; Response.Redirect("Framework.aspx"); } 当我们登录后再从其它页面访问Session["xx"]的时候发现报错说为null.郁闷具体是为什么我也不清楚. 网上百度一下有人做了如下解释,不知道是否合理 原因:当asp.net 执行 respon

php在客户端禁用cookie时让session不失效的解决方法

cookie固然好,不过有些客户端浏览器会禁用cookie,这就会导致你所依赖cookies的程序会失效或出错,那么若真出现用户关闭cookies的情况,PHP应该如何再次使用session?方法还是有的. 1.设置php.ini的session.use_trans_sid = 1或者打开enable-trans-sid选项,让PHP自动跨页传递session id.2.手动通过URL传值.隐藏表单传递session id.3.用文件.数据库等形式保存session_id,在跨页过程中手动调用.

php 不能取得session值的一个解决方法

1.确认下<?php session_start(); ?> 这句话是不是在<HTML> 标志之前.  不在的话,请放到<HTML> 标志之前. 2.如果上面操作后,出现"Warning: session_start() [function.session-start" 信息 解决办法:修改php.ini中的session.auto_start = 0 为 session.auto_start = 1 3.有没有设置session 保存路径 需要修改

foobar2000专辑封面混乱解决方法

foobar2000的专辑封面缓存是调用windows media player的 解决方案: 1.打开windows media player 2.标题栏点击右键,选择工具-高级-还原媒体库,wmp关闭后重新打开会看到所有音乐都被重新添加进了音乐库,再看看,封面是不是都正常了! 来自为知笔记(Wiz)

网站启动SSL, http变为https后,session验证码错误解决方法

网站启动SSL, http变为https后,session验证码错误解决方法 最近公司需要后台启动安全证书,证书安装完毕后,后台老提示 验证码错误,经过几天的研究,此问题已经得到有效解决,现把方法如下. 一.问题展示 看到此问题后,我求助了伟大的互联网,网上大概的解决方法,是说要写两个session,不能相互互通,按照这个思路,我整了几天不见好,后来我重新写了一段代码,问题解决,其实根本不需要写两个session,先公布解决方法. 二.解决方法 原来的验证码代码 <script language

dedecms SESSION变量覆盖导致SQL注入common.inc.php的解决方法

漏洞名称:dedecms SESSION变量覆盖导致SQL注入 补丁文件:/include/common.inc.php 补丁来源:阿里云云盾自研 漏洞描述:dedecms的/plus/advancedsearch.php中,直接从SESSION[SESSION[sqlhash]获取值作为$query带入SQL查询,这个漏洞的利用前提是session.auto_start = 1即开始了自动SESSION会话,云盾团队在dedemcs的变量注册入口进行了通用统一防御,禁止SESSION变量的传入

null id in entry (don&#39;t flush the Session after an exception occurs) 解决方法

最近在学习基于ssh的注解的系统,然后在实现往数据库增加记录时可以增加第一个,第二个就报错,在网上查了很多资料,大多都是 该异常信息是在提示我们没有为数据中的非空字段设置值. 然后就一直没有明白 明明都赋值了 为什么还会这样 ,然后我把unique字段和非空字段去掉即//@Column(name = "zh", unique = true, nullable = false)就好了. null id in entry (don't flush the Session after an