JSP唯一登录及踢人的解决方案

来源:互联网 发布:黑色星期五mac软件 编辑:程序博客网 时间:2024/06/14 16:03

1.问题描述

  同一个帐号只允许一个人登录,在有其他用户登录的时候,给予原登录用户警告提示。

2.分析设计 

     原问题分解成2个小问题:A. 唯一登录;B.踢人

    A.

    (1)第一次发生登录行为的时候的时候将用户信息及sessionId存放到一个实体Bean里,并将这个bean保存到session中。同时以该用户帐号account作为key,帐号对应的sessionId作为值,存到一个Hashtable比如ht里面,并把这个ht保存到ServletContext(暨application)里面永久保存。

    (2)再次发生登录行为的时候,同样首先把用户信息及其sessionId存到实体Bean里面并保存到session。然后从ServletContext里面取出ht,以account做为查询条件判断ht里面是否包含着这个值。如果包含并且其对应的sessionId与当前session里面保存的实体Bean所带的sessionId相同的话,则验证通过,用户的登录是有效的;否则ht里面包含account值但sessionId与session里面保存的bean所带的sessionID不同,则表明发生了同一账户登录行为,将原来的session注销,并更新ht把新的sessionId存放进去。

    (3)实现页面每次刷新都会进行(2)的核对,这样就实现了唯一登录

   B:

    按道理来说,A已经实现了部分的踢人原理,因为原登录用户在刷新页面的时候,就发现自己被注销了session处于未登录状态。但是在这基础上,客户要求发生有人用同一账户登录就立即通知原用户,并中止原用户的一切行为。

    初步考虑有两种方案:

   (1)线程:启用线程控制登录用户

   (2)JavaScript脚本实现:很简单,就是在比较短的时间内,不断的发生刷新页面的行为,进行检测,一旦发生sesionId被更改的情况,就弹出对话框警告用户,并强制刷新页面。

     a.页面不断被刷新是很讨厌的事情,出此考虑,在每个页面嵌入一个隐藏的iframe,iframe链接到一个页面,js脚本控制不断刷新iframe页面。这样对于用户来说是不透明的。除了鼠标的闪动之外,用户的页面是不会发生变化的。而且iframe所链接到的页面仅仅涉及到变量检测,无比较耗费时间的检测,服务器的承受力可以接受。

     b.在js的控制下,可以设置登录后多少时间提示用户,这个时间越长,比如延长到10秒之后,那么对服务器及用户的映像几乎可以忽略。经测试,5秒中后提示给用户的感觉就是立即被踢下去了。

3.部分源码

   初步考虑有两种方案:

   登陆时候的操作:

 /**
  * 用户唯一登陆
  * @param mb
  * @param session
  * @param account
  */
 public void setService(memberBean mb, HttpSession session, String account) {
  session.setAttribute(sessionName, mb);

  if (sc.getAttribute(sessionList) == null) {// 第一次登陆
   Hashtable htb = new Hashtable();
   htb.put(account, session.getId());
   sc.setAttribute(sessionList, htb);
  } else {// 第二次登陆后第一次无效
   Hashtable htb = (Hashtable) sc.getAttribute(sessionList);

   String key = null;

   if (htb.containsKey(account)) {
    //更新session
    htb.remove(account);

   }
   htb.put(account, session.getId());

   sc.setAttribute(sessionList, htb);

  }
 }

  唯一检测:

 /**
  * 检测用户是否登陆
  * @param session
  * @param account
  * @return
  */
 public boolean checkLogin(HttpSession session,String account) ;

iframe的控制:

<script language="JavaScript" type="text/javascript">
<!--
 var counter;
 function iCheckCount() {
  nowTime = new Date().getTime();
  window.frames["iCheck"].src="iCheck.jsp?"+nowTime;
  window.frames["iCheck"].window.location.reload();
  
  counter=setTimeout("iCheckCount()", 5000);
 }
 function stopTimer() {
  clearTimeout(counter);
 }
 
 function startTimer() {
  counter=setTimeout("iCheckCount()", 5000);
 } 

//-->
</script>

4.总结及优化

      踢人的解决方案里,调用了IE窗口的不断刷新,虽然动作行为被隐藏,但是还是存在的。除此之外能不能在线程里做到与客户端交互,彻底的隐藏检测行为,并能够在发生同样登录的情况下唤醒线程,控制客户端窗口,是值得考虑的问题。

     欢迎大家留言讨论。

原创粉丝点击