您的位置:首页 > Web前端 > JavaScript

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

2007-07-01 10:01 141 查看
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窗口的不断刷新,虽然动作行为被隐藏,但是还是存在的。除此之外能不能在线程里做到与客户端交互,彻底的隐藏检测行为,并能够在发生同样登录的情况下唤醒线程,控制客户端窗口,是值得考虑的问题。

欢迎大家留言讨论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: