JavaWeb实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)

JavaWeb实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)的实现思路如下所示:

一、该功能有什么作用

大家想想吧。反正总会有这样的需求的。这年头什么需求不会有。。呵呵。有时候也不一定是需求,很有可能为了安全也会这么做。例如考试系统,在线聊天系统,很有必要做成这样的吧。

二、实现过程

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中的配制

<listener>
<display-name>recordSession</display-name>
<listener-class>com.weirhp.RecordSessionListener</listener-class>
</listener>

三、可能存在的问题

整个个程序可能有的点没有想到。可能存在一些bug,用于具体项目需谨慎,欢迎大家拍砖,也希望给点建议。我再改进。

四、后来的一些思考

  如果两台机器使用同一帐号在同一时刻登录系统,是不是两个帐号都可以登录成功呢。。(还有就是这个session List很大时,在遍历的时间段中两台机器使用同一帐号在同一时刻登录系统也可能会成功登录的)。很是纠结。。应该怎么控制呢?

(解决办法:经测试Listener在系统中是一个单例,在它的方法上加上synchronize关键字就可以保证list的线程安全了。)

以上所述是小编给大家介绍的JavaWeb实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • App登陆java后台处理和用户权限验证

    最近做一个app项目,后台我独自一人开发,开发任务顺序安排上没有把登陆,注册和权限验证这些基本功能放在第一阶段开发,现在是部分业务相关功能已经完成,但是用户入口竟然还没有,只能说明当初需求分析的时候还是太过于着急了,把最基本的用户入口给放到后面了. 现在就需要在现有代码的基础上添加用户登录和权限验证功能. 关于登录和权限验证方面,参照以前做iOS的开发经验,App端提供用户名和密码换取token,每次通过换取的token请求需要登陆权限的操作. 现在反过来,我就需要考虑下面几个问题: 1.在现有

  • java模拟cookie登陆操作

    在使用java访问URL时,如果该URL需要身份验证,那么就不能够直接访问,因为没有登陆.那么,如何解决这个问题呢? 方法是使用java模拟登陆,登陆后记录下cookie信息,在下次发起请求时时将cookie发送过去用以表明身份,这样就能够访问带有权限的URL了. 下面首先介绍使用java模拟登陆. // 连接地址(通过阅读html源代码获得,即为登陆表单提交的URL) String surl = "http://login.goodjobs.cn/index.php/action/UserLo

  • Java的Struts框架中登陆功能的实现和表单处理器的使用

    实现Struts登录 1.jar包拷贝 首先是建立java web项目,之后打开我们我们下载好strtus框架,Struts-1.2.9-bin文件夹和struts-1.2.9.src源文件文件夹.在bin文件夹中的lib文件中拷贝struts的jar包,拷贝到我们自己项目struts_login –>lib文件夹下. 2.web.xml文件配置 找到Struts-1.2.9-bin中Struts-1.2.9-bin-->webapps下的struts实例struts-blank中的strut

  • SpringMVC实现账号只能在一处登陆

    一.问题引导 在Web开发中,实现一个账号只能在一处登陆有两种形式:1.当某个账号在某处登陆后,如果再在其他处登陆,将前一个账号挤掉:2.当某个账号登陆后,此账号在其他设备登陆提示已经登陆,无法登陆. 正常的应用逻辑第一种应用较为广泛,因此此篇文章讨论一下第一种逻辑在spring mvc开发中一种较为简单的实现方式. 然而在没有长连接如WebSocket或者异步请求轮询的情况下,我们之前登陆的账号只能在下一次请求(同步或异步)才能获取被挤掉的状态(如页面跳转). 二.实现步骤 1.建立一个静态M

  • JavaWeb实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)

    JavaWeb实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)的实现思路如下所示: 一.该功能有什么作用 大家想想吧.反正总会有这样的需求的.这年头什么需求不会有..呵呵.有时候也不一定是需求,很有可能为了安全也会这么做.例如考试系统,在线聊天系统,很有必要做成这样的吧. 二.实现过程 a.问题分析 在系统中,我们一般都是把登录信息绑定到session中,看来从这入手是可能找到解决办法.说白了,也就是当用户登录时,判断一下这个用户有没有登录,如果登录了,就把以前的那个session清除

  • Java Web 实现QQ登录功能一个帐号同一时间只能一个人登录

    对于一个帐号在同一时间只能一个人登录,可以通过下面的方法实现: 1 .在用户登录时,把用户添加到一个ArrayList中 2 .再次登录时查看ArrayList中有没有该用户,如果ArrayList中已经存在该用户,则阻止其登录 3 .当用户退出时,需要从该ArrayList中删除该用户,这又分为三种情况 ① 使用注销按钮正常退出 ② 点击浏览器关闭按钮或者用Alt+F4退出,可以用JavaScript捕捉该页面关闭事件, 执行一段Java方法删除ArrayList中的用户 ③ 非正常退出,比如

  • 完全解剖安全帐号管理器(SAM)结构

    安全设置不得不需要了解的东西一.摘要 分析安全帐号管理器结构是在一个多月前做的事情了,只零碎地记录下片段,没有发布过.不发布的主要原因是安全帐户管理器(SAM)是WIN系统帐户管理的核心,并且非常系统化,我也有很多地方仅仅是进行的推断和猜测,同时,SAM hack可能造成启动时lsass.exe加载帐户管理器出错,即便是安全模式也不能修复(启动时候必然加载SAM)使得整个系统启动崩溃(我通常需要依靠第二系统删除SAM文件来启动).至于现在发布出来,主要是因为Adam和叮叮的<克隆管理员帐号>种

  • Serv-U 批量帐号管理及申请(Access+Asp) 图文方法

    1.首先下载Asp程序,在下载中包含Serv-U所需要的数据库,名为Serv#U.mdb.2.建立系统数据源:ftp,通过ODBC进行数据库连接,连接到Serv#U.mdb.步骤如图 3.成功建立ODBC后,打开Serv-U软件,建立FTP域.在步骤4时注意选择Store in ODBC database 4.打开Serv-U安装目录下的ServUDaemon.ini文件,做以下操作:(1)用下面的代码覆盖原来的ODBCSource.ODBCTables.ODBCColumns---------

  • 易语言SMTP验证帐号、密码教程

    易语言通过SMTP验证帐号.密码 1.打开易语言>>>>新建一个窗口程序打开易语言>>>>新建一个窗口程序 2.一次添加两个标签.两个编辑框.一个按钮 3.用到的两个编辑框,一个作为帐号编辑框,一个作为密码编辑框.用到的两个编辑框,一个作为帐号编辑框,一个作为密码编辑框. 4.输入代码: .版本 2 .支持库 internet .程序集 窗口程序集1 .子程序 _按钮1_被单击 .判断开始 (连接发信服务器 ("smtp.163.com"

  • 同一个帐号不能同时登陆的问题

    〓简介〓有点常识的人都知道本身用asp做这种功能显然有些牵强,因为他不像qq,msn或irc 聊天室那样是即时通讯,他都是靠刷新网页更改最后活动时间来获取用户是否在线的,所以您不要指望下面这片教程有多完美,我也只是把我的思维模式记录下来,有啥不对的地方还请高手们多多指教!--------------------------------------------------------------------------------〓正文〓首先我先向大家介绍一下我实现这个效果的思路,如果你看过我的思

  • 利用SQL SERVER建立登录WINDOWS帐号

    那一刻,我的心跳到了嗓子眼. 运行建立帐号命令,OK! 远程登录,输入帐号,密码,OK!终于又进去了! ××××××××××××××××××× 我忽然发现,数据库服务器登录不了了. 提示帐号密码过期.按提示修改,提交,又说我没权限修改密码! CNM,这样来害我.这个帐号属于administrators,原先那个默认的administrator被我停掉了.因此这个帐号是进入系统的唯一通道. 接着发现后果比我想象的要严重更多: 1.硬盘做了RAID5,这样即使拿到硬盘,可能也读不出数据库文件了. 2

  • 微信公众帐号开发-自定义菜单的创建及菜单事件响应的实例

    微信开发公众平台自定义菜单需要花钱认证才能实现,不想花钱只能玩测试账号了,不过这并不影响开发.我的开发都是基于柳峰老师的微信公众平台应用开发做的. 只要我们使用公众平台测试账号就可以开发自定义菜单了,比较方便,测试账号开放了很多接口,很方便. 在开发自定义菜单的时候可以参考微信公众平台开发者文档的自定义菜单创建. 一.自定义菜单 1.自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单. 2.一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替. 3

  • js读写COOKIE实现记住帐号或密码的代码(js读写COOKIE)

    js COOKIE 记住帐号或密码 function onLoginLoaded() { if(isPostBack == "False") { GetLastUser(); } } function GetLastUser() { var id = "49BAC005-7D5B-4231-8CEA-16939BEACD67"; var usr = GetCookie(id); if(usr != null) { document.getElementById('t

  • .Net微信网页开发解决用户在不同公众号或在公众号、移动应用之间帐号统一问题

    开发背景: 最近一段时间一直在做关于微信方面的网站应用开发,这段时间也收获的不少关于微信开发方面的开发技能,接触的比较多的主要有微信公众号和微信网站app第三方登录授权,以及微信会员卡,优惠券和扫描二位码的功能,今天我主要想要总结的是微信公众号登录和网站app第三方应用微信授权登录这两者之间获取到的Openid关联问题,实现两边登录都是同一个账号. 首先我们必须区别开来微信公众平台开发是指微信公众号进行业务开发(https://mp.weixin.qq.com/wiki?t=resource/r

随机推荐