一、该功能有什么作用
大家想想吧。反正总会有这样的需求的。这年头什么需求不会有。。呵呵。有时候也不一定是需求,很有可能为了安全也会这么做。例如考试系统,在线聊天系统,很有必要做成这样的吧。
二、实现过程
a.问题分析
在系统中,我们一般都是把登录信息绑定到session中,看来从这入手是可能找到解决办法。说白了,也就是当用户登录时,判断一下这个用
户有没有登录,如果登录了,就把以前的那个session清除掉就OK了。。看似很简单是不?其实你细想你会发现有以下问题:如何得到之前这个用户有没有
登录过,也就是如何访问到所有登录的session信息呢?
b.具体实现
大家知道,在j2ee api好像是没有具体的方法直接得到所有session信息的。但是我们可以通过配制监听器,监控所有的session创建和消毁过程,以及可以监控session中的属性的创建,删除和替换过程。
其实我们只要做以下处理即可:
在保存用户登录信息到session时,对应的也就是session一个属性的创建过程(attributeAdded),可以把当前这个session记录到一个ArrayList中。
其实在保存到list中时你要首先遍历一下这个list中有没有已经存在该用户的登录信息。如果存在就消毁掉这个list中存在的session信息,并且从list中移除,不存在就把该session信息放到list中。
在session的登录信息消毁时,直接把该sesseion从list中移除掉。
还有就是当用户登录后没有退出直接登录这个时候是一个session属性的替换过程。也要做处理判断新的用户是否已经在除了当前session的其它session中是否存在。存在则删除。
具体代码如下:
package com.weirhp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public
class
RecordSessionListener implements HttpSessionAttributeListener,
HttpSessionListener {
private
static
List
<
SessionAndUser
>
sessions;
public
static
String loginFlag
=
"
loginUser
"
;
static
{
if
(sessions
==
null
) {
sessions
=
Collections.synchronizedList(
new
ArrayList
<
SessionAndUser
>
());
}
}
public
void
attributeAdded(HttpSessionBindingEvent e) {
HttpSession session
=
e.getSession();
System.
out
.println(
"
-------------*start added*-----------------------
"
);
String attrName
=
e.getName();
//
登录
if
(attrName.equals(loginFlag)) {
User nowUser
=
(User) e.getValue();
User sUser
=
(User)session.getAttribute(loginFlag);
//
遍历所有session
for
(
int
i
=
sessions.size()
-
1
; i
>=
0
; i
--
) {
SessionAndUser tem
=
sessions.
get
(i);
if
(tem.getUserID().equals(nowUser.getName())) {
tem.getSession().invalidate();
//
自动调用remove
break
;
}
}
SessionAndUser sau
=
new
SessionAndUser();
sau.setUserID(nowUser.getName());
sau.setSession(session);
sau.setSid(session.getId());
sessions.add(sau);
}
}
public
void
attributeRemoved(HttpSessionBindingEvent e) {
HttpSession session
=
e.getSession();
System.
out
.println(
"
-------------*start Removed*-----------------------
"
);
String attrName
=
e.getName();
//
登录
if
(attrName.equals(loginFlag)) {
User nowUser
=
(User) e.getValue();
//
遍历所有session
for
(
int
i
=
sessions.size()
-
1
; i
>=
0
; i
--
) {
SessionAndUser tem
=
sessions.
get
(i);
if
(tem.getUserID().equals(nowUser.getName())) {
sessions.remove(i);
break
;
}
}
}
}
public
void
attributeReplaced(HttpSessionBindingEvent e) {
HttpSession session
=
e.getSession();
System.
out
.println(
"
-------------*start replace*-----------------------
"
);
String attrName
=
e.getName();
int
delS
=-
1
;
//
登录
if
(attrName.equals(loginFlag)) {
//
User nowUser = (User) e.getValue();
//
old value
User nowUser
=
(User)session.getAttribute(loginFlag);
//
当前session中的user
//
遍历所有session
for
(
int
i
=
sessions.size()
-
1
; i
>=
0
; i
--
) {
SessionAndUser tem
=
sessions.
get
(i);
if
(tem.getUserID().equals(nowUser.getName())
&&!
tem.getSid().equals(session.getId())) {
System.
out
.println(
"
Remove:invalidate 1!
"
);
delS
=
i;
}
else
if
(tem.getSid().equals(session.getId())){
tem.setUserID(nowUser.getName());
}
}
if
(delS
!=-
1
) {
sessions.
get
(delS).getSession().invalidate();
//
失效时自动调用了remove方法。也就会把它从sessions中移除了
}
}
}
public
void
sessionCreated(HttpSessionEvent e) {
}
public
void
sessionDestroyed(HttpSessionEvent e) {
}
}
在web.xml中的配制
1
<
listener
>
2
<
display-name
>
recordSession
</
display-name
>
3
<
listener-class
>
com.weirhp.RecordSessionListener
</
listener-class
>
4
</
listener
>
三、具体代码测试
源代码下载
四、可能存在的问题
整个个程序可能有的点没有想到。可能存在一些bug,用于具体项目需谨慎,欢迎大家拍砖,也希望给点建议。我再改进。
五、后来的一些思考
如果两台机器使用同一帐号在同一时刻登录系统,是不是两个帐号都可以登录成功呢。。(还有就是这个session List很大时,在遍历的时间段中两台机器使用同一帐号在同一时刻登录系统也可能会成功登录的)。很是纠结。。应该怎么控制呢?
(解决办法:经测试Listener在系统中是一个单例,在它的方法上加上
synchronize
关键字就可以保证list的线程安全了。)
转载出处http://www.cnblogs.com/weirhp/archive/2011/05/08/sesssionlistener.html
分享到:
相关推荐
在JavaWeb开发中,实现同一账号同一时间只能在一个地点登录的功能,主要目的是为了增强系统的安全性,防止用户账户被他人恶意登录或同时在多个设备上使用,例如在在线考试系统、即时通讯应用等场景中尤为关键。...
java Web 同一个用户名不能同时登陆的思路 .doc ...java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能).doc java中如何实现同一账号不能同时登录.doc session保证两用户不能同时登陆一个账号.doc
本解决方案主要关注如何利用DWR来实现一个用户在同一时间只能登录一次的功能,类似于QQ的单点登录机制。 首先,我们需要理解DWR的基本工作原理。DWR允许JavaScript直接调用服务器端的Java方法,并将结果返回到...
在Java Web开发中,实现QQ登录功能并限制一个账号同一时间只能一个人登录,涉及到的关键技术包括用户会话管理、状态跟踪以及异常情况处理。以下是对这个功能实现的详细解析: 首先,我们需要一个全局的存储结构来...
例如,在即时通讯软件如QQ中,如果一个账号在另一台设备上登录,则原先的登录会自动断开。本知识点主要介绍一种利用Java的`session`技术配合`session`监听器来实现这一功能的方法。 #### 实现原理与步骤 为了实现...
这里我们探讨的是一种集群环境下的解决方案,它允许我们确保一个账号在同一时间只能在一个地方登录,即实现“单点登录”功能。这个方案主要基于Spring Boot和Redis技术栈来实施。 **Spring Boot** 是一种基于Java的...
根据提供的文件信息,文档主要描述了如何使用JSP和servlet技术实现一个特定功能:当同一用户尝试在不同位置登录时,能够“挤掉”之前的登录会话,且实现这一过程时页面不需要刷新。 ### 关键知识点解析 #### 1. ...
【标题】"精选_基于JAVA的局域网聊天软件的设计与实现(仿制QQ)_源码打包"揭示了这是一个关于使用Java编程语言开发的局域网聊天应用项目,旨在模仿QQ的功能。这个软件的设计和实现涉及到网络通信、图形用户界面(GUI...
在Java Web开发中,Cookie是一种常用的客户端存储机制,它用于在用户浏览器中保存少量信息,以便在用户访问网站的不同页面时能够保持用户的登录状态。"JAVA cookie记住登录状态10天"这个主题主要关注如何利用Cookie...
在本场景中,"ssh写的用户登录权限实现"指的是使用SSH协议来控制用户登录的权限,确保在同一时间只有一个用户能够使用特定的账号登录系统。这种机制可以防止未经授权的并发登录,增加系统的安全性。 Struts2、...
下面是一个简单的Java示例代码,展示了如何实现用户登录状态的管理和检测异地登录的功能: ```java public class User implements HttpSessionBindingListener { private static java.util.Vector allUsers = new ...
- 设计一个清晰易用的登录界面,提供QQ登录选项,并支持用户选择不同的账号登录。 - 在登录成功后,应显示用户的基本信息(如头像、昵称等),提高用户体验感。 9. **安全性考虑** - 在实现过程中,需要关注...
Java在线聊天系统是一种基于Web的即时通讯应用,它利用了Java技术栈来实现用户之间的实时通信功能,类似于我们在日常生活中使用的浏览器版QQ。这个系统可以让多个用户在同一时间进行互动交流,提供了一个便捷、高效...
Java是一种广泛使用的编程语言,尤其在开发Web应用时,它提供了丰富的库和工具来实现各种功能,其中之一就是生成和验证验证码。验证码(CAPTCHA)的主要目的是防止自动化程序(如机器人)进行恶意操作,例如批量注册...
验证码软件包是一个专门为Java开发者设计的工具,旨在简化Web应用中的验证码实现过程。这个软件包遵循了Apache 2.0开源许可协议,这意味着它允许用户自由地使用、修改和分发代码,为开发者提供了极大的灵活性和便利...
- **继承**:继承允许一个类继承另一个类的属性和方法,从而实现代码的复用。书中可能会通过实例介绍如何在Java中实现继承。 - **多态**:多态是指允许不同子类型的对象对同一消息做出响应的能力。Java中的多态主要...
《Java基础案例教程(第2版)》是一本旨在教授初学者Java编程基础知识的教材,其PPT形式的压缩包提供了清晰、直观的教学材料。在深入探讨这些知识点之前,我们首先了解一下Java语言的基础概念。 Java是一种面向对象...
- **简单服务器与客户端**:创建一个简单的TCP或UDP服务器和客户端,实践网络通信。 - **Web应用开发**:使用Servlet和JSP实现基于HTTP的Web应用。 10. **高级话题**: - **NIO(非阻塞I/O)**:Java的NIO库提供...