一、该功能有什么作用
大家想想吧。反正总会有这样的需求的。这年头什么需求不会有。。呵呵。有时候也不一定是需求,很有可能为了安全也会这么做。例如考试系统,在线聊天系统,很有必要做成这样的吧。
二、实现过程
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开发中,实现同一账号同一时间只能在一个地点登录的功能,主要目的是为了增强系统的安全性,防止用户账户被他人恶意登录或同时在多个设备上使用,例如在在线考试系统、即时通讯应用等场景中尤为关键。...
在IT行业中,"同一个账号,同一时间只能允许他登录一次" 这个需求通常被称为单点登录(Single Sign-On, SSO)。这是一个重要的安全性措施,防止用户账户被多个设备或不同地点同时使用,以增加系统的安全性,防止未经...
标题提到的“ASP帐号只能同时登陆一个”,指的是同一个账号在同一时间只能在一个设备或浏览器会话上登录,这通常被称为单点登录(Single Sign-On, SSO)机制。 单点登录的设计目的是为了增强安全性,防止同一账号被...
3. **处理登录冲突**:一旦检测到同一账号在不同位置尝试登录,系统会将之前的登录状态`Login_status`设置回0,强制下线之前的登录会话,从而确保同一账号在同一时间只能在一个地方登录。 #### 利用ASP.NET管理登录...
下面将详细解释两种实现这一功能的方法:使用Session和在数据库中设置一个字段。 **方法一:使用Session** Session是Web服务器为每个客户端(浏览器)创建的一种存储机制,用来存储特定用户会话的信息。当用户登录...
简单来说,就是确保系统中的每个用户在同一时间内只能在一个地方进行登录操作。这有助于避免因用户在不同设备或浏览器上同时保持登录状态而导致的安全问题或数据混淆情况发生。 #### 技术实现方法 实现这一功能的...
因此,限制同一用户账户在同一时间只能在一个地方登录是非常必要的。 #### 二、实现原理及步骤 本文介绍的方法主要是通过ASP.NET中的全局状态存储机制来实现的,具体步骤如下: 1. **使用Application对象存储在线...
通过以上步骤,我们就可以在Spring Security框架下实现单点登录,确保用户在同一时间只能在一个设备或浏览器上登录。这样的机制有助于提高系统的安全性,防止账户被恶意操作。标签“源码”表明了可能需要深入阅读和...
在IT行业中,尤其是在开发多用户应用时,"同一账号不能两次登陆实现" 是一个重要的功能需求,它确保了用户账号的安全性和唯一性。这个功能的主要目的是防止同一账号在不同的设备或者浏览器上同时登录,以避免账号被...
4. **会话唯一性**:为了确保一个账号只能在一个地方登录,我们可以创建一个额外的会话标志,例如`$_SESSION['single_login']`。在用户首次登录时,将其设置为真,并在数据库中记录该用户的会话ID。 5. **检测多处...
java web开发一个帐号同一时间只能一个人登录 .doc java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能).doc java中如何实现同一账号不能同时登录.doc session保证两用户不能同时登陆一个账号.doc
在Java Web开发中,实现QQ登录功能并限制一个账号同一时间只能一个人登录,涉及到的关键技术包括用户会话管理、状态跟踪以及异常情况处理。以下是对这个功能实现的详细解析: 首先,我们需要一个全局的存储结构来...
然而,在多人共享同一账号的情况下,如何有效地控制该账号只能在一个地方登录成为了一个值得探讨的技术问题。 #### 解决方案 根据hty4000的描述,最佳解决方案是在通达OA2008ADV的配置文件中进行相应的设置调整。...
在C#编程中,"同一个账号只能登录一次"的需求是一个常见的多用户系统设计规范,它旨在确保用户账户的安全性和系统的一致性。当一个账号在一处登录后,其他地方的同一账号尝试登录时,系统应该拒绝该请求或者强制结束...
在ASP.NET开发中,确保系统安全性的一个关键方面是防止同一用户在同一时间从多个设备或浏览器窗口登录。这种安全措施不仅可以防止潜在的安全威胁,如账户冒用,还可以避免因多处登录而造成的资源浪费和数据冲突。...
很多开发者都会遇到这样的情况:如何使同一个用户在同一时间内只允许登录一次。常见的解决方案是使用数据库中标识字段,登录时置 1,退出时置 0,但是这种方法存在一些问题,如用户直接关闭浏览器而不是通过程序中的...
在多用户环境中,确保一个ASP.NET网页在同一时刻仅被一个登录用户占用是非常重要的,这涉及到用户体验、数据一致性和安全性。这种需求通常被称为“独占访问”或“会话锁定”。 在ASP.NET中,实现独占访问的一种常见...
在实际的应用场景中,为了提高系统的安全性以及用户体验,很多系统都需要实现同一个用户在同一时间只能在一个地方登录的功能。这样的设计可以有效避免用户账号被恶意盗用的风险,并且能够确保数据的安全性。在 ASP...
这个程序的核心理念是确保同一时间只有一个用户能够使用特定的账号进行登录,防止了多个人同时操作同一账号的情况,增加了系统的安全性。 首先,我们需要理解这个程序的基本架构。它通常包含以下几个关键部分: 1....