jsp:同一个用户帐号,在同一时间内只能一个人使用

时间:2021-11-29 14:40:20
关于这个问题,我也看了很多的帖子,但是,基本都是那种零零散散的,不知道那位高手对这种有何看法。如果好的话,我还会加分,再100分。希望高手踊跃发言啊。

78 个解决方案

#1


无语了,我怎么发了两个啊。都是网站的问题啊。我只是刷新一下,它又提交了啊。这不是浪费我分数吗。

#2


无非是状态记录而已
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样
还有一个就是用数据库记录
也是同一个实现方式

#3


登陆时判断ServletContext中是否有该用户帐号,有则拒绝,没有就把该用户帐号放入ServletContext,实现一个HttpSessionListener
在session过期时把该用户帐号从ServletContext中删除,注意一下并发访问

#4


给用户信息增加一个used的标志,
1 每次登录时,将标志更新为 true
2 每次退出登录时,将标志更新为 false;
3 每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了
4 如果不在线,则更新标志为false

#5


每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了
我就有了一个疑问了,那就是如果一个用户下线了,然后马上登录,那就不可能登陆啊,要等到一段时间才能登录。这样的话就成了问题了啊

#6


其实主要重点应该是用户离线考虑问题,希望高手,多提点提点

#7


可以把sessionid放到数据库里,同一个人每次登陆的时候去数据库中把现在的sessionid更新到数据库,

然后页面上的每一个和服务器交互的操作都要去验证现在的sessionid和数据库里自己用户名对应的sessionid是不是一样,如果一样就说明这个用户名就一个人在登录,一切操作正常,如果不一致说明已经又有人用这个用户名登录了,那现在的这个页面就不能用了,你让它跳转到登陆页面。

这种做法就是最后登录的人有效!!!我们有个项目就是这样作的  但是不知道这样做好不好,如果楼主有什么没有明白的可以再联系我,我一般时都在

#8


引用 4 楼 java2000_net 的回复:
给用户信息增加一个used的标志,
1 每次登录时,将标志更新为 true
2 每次退出登录时,将标志更新为 false;
3 每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了
4 如果不在线,则更新标志为false


有道理,顶一个。

#9


引用 2 楼 little06 的回复:
无非是状态记录而已 
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出 
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除 
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样 
还有一个就是用数据库记录 
也是同一个实现方式


楼主上网找找  单点登陆  咯

就是说的你这个问题

网上应该有很多说这个的,也蛮容易的,偶也想搞,不过现在冒时间,呵呵

#10


acegi有一个concurrent session,设置成1就只能登录一个人咯。

#11


10楼我看过你的看法有点不一样,可以不可以说清楚点啊。还有7楼的,就是用户离开了你怎么处理(比如说点击ie关闭按钮那你怎么处理用户,此时用户已经离线了啊,那怎么处理啊)

#12


Application 里维护一个全局变量就可以了

#13


Application 里维护一个全局变量就可以了,因为Application每个服务器或者web程序职能有一个,在Application范围维护一个全局变量,当第一次登陆就把这个变量置为true,再次登陆判断一下,如果是true就表明已经登陆了一个,就不可以登陆了,很简单吗

#14


明确告诉你,为了你的程序的可用性,你不可能知道用户的准确在线信息。除非你安装插件

比如 flash/applet/activeX

让他们不停的访问服务器,告诉服务器我还活着..... 不过你的服务器得足够好才行。。。

#15


14楼有这种事啊。那就是说,如果一个用户一下线不可能马上知道它下线是否,是不是这个意思啊。我想了解更多点啊。麻烦告诉我,

#16


明确告诉你,为了你的程序的可用性,你不可能知道用户的准确在线信息。除非你安装插件 

比如 flash/applet/activeX 

让他们不停的访问服务器,告诉服务器我还活着..... 不过你的服务器得足够好才行。。。


可不可以说明白点啊。如果一个用户一下线不可能马上知道它下线是否下线,只有通过插件吗。是这样吗。我想了解一下,
可以不可以说明白点啊

#17


很简单 {后来的顶掉前面的}

每个登陆用户有一个SESSION(其中放置登陆用户ID [USERID]) 每个SESSION有一个 SESSION_ID(这个应该是唯一的)

建立一个全局变量字典 
每个新登陆成功的用户 在字典中建立或者覆盖 USERID/SESSION_ID(一个用户登陆第2次 后来的必定覆盖前面的信息)

然后 用户在SERVLET或者JSO执行时 在全局字典中 查询 当前的USERID 获取的SESSION_ID是否是 当前SESSION的SESSION_ID
不一样 就证明已经 被其他地方登陆掉了 则不执行 任何命令

#18


这个问题我曾经弄过

我在blog上写了两篇相关文章,你可以参考一下
《同一时间同一帐号只能登陆一个》
http://heisetoufa.ggblog.com/296626.html

----------------------------------------------------------------

后登陆的用户会把先登陆的用户踢下线

具体实现:sessionCheck:

package test;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionMapping;

public class sessionCheck 
{
 
 private static sessionCheck sessioncheck;
 public sessionCheck(HttpServlet servlet) 
 {
 }
 public static sessionCheck getInstance(HttpServlet servlet) 
 {
  if (sessioncheck==null)
  {
   sessioncheck=new sessionCheck(servlet);
  }
  return sessioncheck;
 } 
 public void setSession(String userName,HttpServlet servlet,HttpSession session,ActionMapping mapping) 
 {
        final ServletContext sc = servlet.getServletContext();//取得容器,容器中根据用户唯一标识userID存放session
        System.out.println(sc);
        System.out.println(session);
        if (sc.getAttribute(userName) != null) 
        {
         // 第二次登陆后第一次无效
            ((HttpSession) sc.getAttribute(userName)).invalidate();// 清除第一次登陆的session
            System.out.println(session);
        }
        sc.setAttribute(userName, session);//放入当前最新session
        mapping.findForward("sessionDestroy") ;
    }

}

UserLoginForm:

sessionCheck.getInstance(this.getServlet()).setSession(userName, servlet, session, mapping);

jsp:

<body ="sessionDestroy()">

< language="java" type="text/java">
sessionDestroy()
{
  alert("连接超时,或帐号已在别处登陆,请查证后重新登陆");
  location.href = "UserLogin.jsp" ;
}
</> 
这样在两台电脑上后登陆的人用户就会把先登陆的给踢掉,但是暂时还没实现在同一台电脑上后登陆的用户把先登陆的踢掉的功能

上面是在后台实现的,如果要在JSP中做,直接appliction.getAttribute(userId),appliction.setAttribute(userId,   session)就行,application的我还没有去测试,有时间去试一下去

#19


在帐号表中加个状态字段,
登录时更改该字段
判断是否被使用

#20


给数据库存储userid的表加一个登陆标志字段,每次登陆进行一下过滤不就行了吗。

#21


每个用户登录都会存下用户的信息,你可以真对这些信息判断,如果为空,就可以登录,如果存在,也就是不为空,你就不能在登录,说明用户正在使用呀,

#22


session有一个监听器,当session销毁时它可以知道。
继承这个监听器,并配置。
在调用时,把用户信息从session中取出,将数据库中对应用户的状态修改。

#23


知道有个东西叫SSO  ,有很多单点登陆的开源产品,也可以自己架设。

可以打通多域名网站 ,也可以控制像你说的那样

#24


引用 2 楼 little06 的回复:
无非是状态记录而已 
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出 
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除 
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样 
还有一个就是用数据库记录 
也是同一个实现方式

#25


其实关键是用户下线判断问题,好象楼上的已经解决了.

#26


你们有自己的看法蛮写上来,没事。我把分数加了100了一共150,写的好的话,多加分。

#27


无非是状态记录而已  
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出  
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除  
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样  
还有一个就是用数据库记录  
也是同一个实现方式 

#28


引用 12 楼 KKK2007 的回复:
Application 里维护一个全局变量就可以了

我觉得这个比较好!

#29


我也做过这样一个项目,我的解决方法是这样的:(相互学习)
建一个用户在线表,用户登陆就判断在线表中是否有此用户,如果有,提示不能重复登陆,没有则成功登陆.
这就要解决用户退出的问题,就是说用户退出删除表中用户的问题.
有几种情况
1,用户点击系统指定退出按钮,系统从数据库中删除在线表中的用户.这个实现很简单就不说了.
2,用户点窗口上的关闭(X)来关闭页面.在JAVASCRIPT里面写一个window.onbeforeunload函数.
window.onbeforeunload = function () {
if (event.clientX > document.body.clientWidth && event.clientY < 0 || event.altKey) {
window.document.forms[0].submit();
alert("\u4f60\u5df2\u5b89\u5168\u9000\u51fa!");
}
}
执行一个form提交,去数据库中删除在线用户.
3,如果用户直接关闭电脑,就是说非正常关机,这个就不好处理了.要用SESSION来判断,如果SESSION失效,则系统自动从数据库中去删除用户,但WEB中的SESSION是服务器端的,不能实时处理用户退出问题,就只有设置SESSION失效时间.
写一个Listener继承HttpSessionListener在sessionDestroyed()方法中执行数据库删除操作.


以上基本可以满足一般系统要求,当然还有一点就是,当服务器启动则执行在线表的清空操作.客户不喜欢每次重启服务器都要手工去表中删除未清空的在线用户.
写一个SERVLET让其在容器启时自动启动,设置WEB.XML中的<load-on-startup>为一数字即可.
还有什么没有写到的地方望大家赐教.

#30


不好意思,刚才是从代码中拷的.
那个ALERT("")里面的意思是"您已安全退出!"

#31


1、状态记录意义不大,因为HTTP本质上是无状态的,你不知道谁在线,因此只能实现后面的有效登入踢掉前面的登入,那么,所谓的后面和前面需要更多的信息来判断,仅仅一个状态毫无意义,一般的处理是以登入机器的特征,比如IP,Cookie等的演算,判断新的登入与先前的登入演算码是否一致
2、由上,新的登入之后,最节省识别方式可能是在浏览器和WEB Svr 之间互通一个登入随机数(新登入时产生),该数可以存储在任何合理的地方,传输通道最合理的应该是session cookie,也可以是请求参数

#32


这个问题我也曾经碰到过,有人说加个字段来标识是否登录,也有人用HashTable来存,还有人用监听器来监听SESSION,更有人让服务器每秒刷新来判断SESSION是否还存活……
但这些方法都不能完全解决你的问题。因为,如果遇到突然断电或者直接关闭浏览器窗口之类的事件,不仅不会更改数据库,更不会被监听到...

其实我也是说大话,至今也不知道解决的好办法。
不过,一般的WEB程序要求都不至于这样严格,把密码之类的安全性做高点就OK了

#33


我只是接分來的。。。。

#34


一起来建设我们的Software   Coffee   House(SCH) 
CSDN群 招募中……

#35


这个问题也真的是不怎么好回答。
我也只学JSP一个月
我个人的观点
JSP不是有COOKIE的功能吗。
不能说是功能,
如果他登陆 我可以更新他的
以下借用的啊:
给用户信息增加一个used的标志, 
1 每次登录时,将标志更新为 true 
2 每次退出登录时,将标志更新为 false; 
3 如果不在线,则更新标志为false 
以下自己的观点:
如果他点浏览器关闭 我会话肯定不是原来的了
但是我可以用过滤器过滤 得到他的COOKIE中保存的信息 进行验证
为TRUE的话 我可以给他创建会话。
当他点退出的时候
我可以把他COOKIE的内容给销毁掉
不知道是不是答非所问了

#36


还有会话。

#37


关注ing!

#38


HTTP的特性决定不可能完全准确的判断用户何时离线。所以不现实也没必要精确地刷新在线的用户信息,有一定的时间冷却是可以接受的。而冷却时间要看你的服务器了。

#39


其实,那些说容易的人根本就连楼主的问题都没有搞明白

最本质的原因在于http协议在一定能够的程度上可以说是一种残疾的协议
只能由客服端单纯的“拉”取数据,而不能想像tcp/ip一样实现三次握手
服务端也不能“推”数据,他是一种无状态的协议,,我们很难判别浏览器
在什么时候推出,异常的结束会话!这也是问题的关系!
acegi我还没有研究过,
但是我有种思路就是
1)设置用户合法注销,给出链接,至于是去在数据库还是application里面加状态字,随情况定
2)用户点击关闭按钮的时候,发送ajax请求,请求后端注销账号
但是,不能应付用户在任务管理器种关闭进程的方式
期望高手给出完美解决方案

#40


ls的这么多解决方案还不能解决你的问题吗?

如果服务器好的话,用session比较简单


或者用插件。

#41


补充一下
如果服务器足够健壮的话
我们可以考虑在客服端设置一个一定时间间隔的触发器
每次都像后台发送“userid”这个字段,后台可以根据time>时间间隔
的情况判断用户是否”生存“,加控件的话,不好的地方在于我们大多数要求
我们的程序能够跨越浏览器生存

#42


在JAVA中,你能用SESSION来判断,SESSION在登陆的时候,会监听到新SESSION的创建,这样,你可以用ARRAYLIST来保存这个登陆成功的用户ID,SESSION设置超时1小时清除。
如果有人在其他地方登陆,那么首先读ARRAYLIST保存的用户ID,如果ID存在,则证明此ID已被他人登陆中,提示不能重复登陆。
具体代码:

public class User implements HttpSessionBindingListener {

   private int userid;
//GETTS,SETTS METHODS ADD IN HERE
public void valueBound(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
System.out.println("add some one");
System.out.println("userid:"+userid);
boolean isExists=userList.contains(Integer.toString(userid));
if(isExists==false)
userList.addUser(Integer.toString(userid));
}


public void valueUnbound(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
System.out.println("remove some one");
System.out.println("userid:"+userid);
boolean isExists=userList.contains(Integer.toString(userid));
if(isExists==true)
userList.removeUser(Integer.toString(userid));
}
}


完整代码比较长,要涉及你的登陆系统怎么来做的,但上面是最关键核心的代码,结合我的描述,你实现出来应该不难

#43


引用 42 楼 cchaha 的回复:
在JAVA中,你能用SESSION来判断,SESSION在登陆的时候,会监听到新SESSION的创建,这样,你可以用ARRAYLIST来保存这个登陆成功的用户ID,SESSION设置超时1小时清除。 
如果有人在其他地方登陆,那么首先读ARRAYLIST保存的用户ID,如果ID存在,则证明此ID已被他人登陆中,提示不能重复登陆。 
具体代码: 

Java code
public class User implements HttpSessionBindingListener {

   private int userid;
//GETTS,SETTS …


瞎激情;
关键问题在于我们是否可以尽量的缩短你的这个一小时时间差,我加入在这一小时之间登陆的时候,
那且不是要等待一个小时;

所以,这里的发言2/3可以完全过滤掉!

#44


是个比较麻烦的事情,用新的顶掉旧的应该不错,关注

#45


个人感觉新的定旧的不错,新登入的直接覆盖掉旧的,至于旧的请求可以根据sessionID来判断是不是最新,不是就提示,并要求重新登入。这样感觉是最简单的。

还有就是旧的不能顶新的,上面已经有很多人提供方法了,关键就是退出的问题,其实没有必要管理这个退出,只要当前判断当前用户正在使用(方法上面已经说了很多了),就不让新的用户登陆就是,然后在设置一个选项,强制登陆,在强制登陆的情况下 ,就会覆盖掉旧的。这样应该能适合一些情况吧。或者加个选项不允许强制登陆,使强制登陆失效,但这样情况下,可以为系统设置一个检测时间,如:30分钟内该用户没有响应就自动掉线,或者失效。这2个方法结合应该能稍微能改善点吧

#46


假设用户A先使用帐号s登陆,用户B后使用帐号s登陆。
处理情况分两种:
一、不允许B登陆
  1、数据库创建标记位。
  2、创建map表存储userName-->sessionId。
  两种方法,缺点:当用户A在未正常退出---session失效的时间内,帐号s无法使用。即使可以监听到用户关闭浏览器,也无法监听到用户从任务管理器关闭浏览器、
                  浏览器错误甚至机器断电。所以不建议使用此方法。

二、踢掉用户A
  1、数据库记录sessionId。
  2、创建map表存储userName-->sessionId。
  原理:以map表为例,当用户A登陆时,读取userName对应的sessionId,如果存在则覆盖之,不存在,则添加到map表,map表数据如:s-->sessionIdA.
        当用户B登陆时,做同样操作,map表数据如:s-->seesionIdB。当A再次发出请求时(非登陆请求),读取userName对应的sessionId,
        sessionIdA(A的请求携带的)!=sessionIdB(map表中读取的),设置sessionIdA无效,跳回登陆页,要求登陆。
        只需要建一个filter过滤登陆请求,一个filter过滤非登陆请求。

#47


请求走的本来就是无状态协议
如果想做的实时精度高的
看看server push
http://topic.csdn.net/t/20000704/10/13930.html
不断线,服务端向客户端推的技术吧

#48


引用 5 楼 wlj11111 的回复:
每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了 
我就有了一个疑问了,那就是如果一个用户下线了,然后马上登录,那就不可能登陆啊,要等到一段时间才能登录。这样的话就成了问题了啊


可以使用Session啊,登录了就记在Session中,下次有用户登录就与Session中存的比较,有相同的就不允许登录,否则就可以登录
用户一退出就马上注销Session,这样就不存在这样的问题了

#49


引用 48 楼 import_jsp 的回复:
引用 5 楼 wlj11111 的回复:
每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了  
我就有了一个疑问了,那就是如果一个用户下线了,然后马上登录,那就不可能登陆啊,要等到一段时间才能登录。这样的话就成了问题了啊 
 

可以使用Session啊,登录了就记在Session中,下次有用户登录就与Session中存的比较,有相同的就不允许登录,否则就可以登录 
用户一退出就马上注销Session,这样就不存…


这位仁兄貌似有点没搞清楚状况,站着说话不腰疼,知道大家都在讨论什么不
用户一退出就马上注销session,你以为在玩c/s呢

#50


明天结贴还有谁有自己的看法的啊,蛮写上来吧。

#1


无语了,我怎么发了两个啊。都是网站的问题啊。我只是刷新一下,它又提交了啊。这不是浪费我分数吗。

#2


无非是状态记录而已
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样
还有一个就是用数据库记录
也是同一个实现方式

#3


登陆时判断ServletContext中是否有该用户帐号,有则拒绝,没有就把该用户帐号放入ServletContext,实现一个HttpSessionListener
在session过期时把该用户帐号从ServletContext中删除,注意一下并发访问

#4


给用户信息增加一个used的标志,
1 每次登录时,将标志更新为 true
2 每次退出登录时,将标志更新为 false;
3 每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了
4 如果不在线,则更新标志为false

#5


每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了
我就有了一个疑问了,那就是如果一个用户下线了,然后马上登录,那就不可能登陆啊,要等到一段时间才能登录。这样的话就成了问题了啊

#6


其实主要重点应该是用户离线考虑问题,希望高手,多提点提点

#7


可以把sessionid放到数据库里,同一个人每次登陆的时候去数据库中把现在的sessionid更新到数据库,

然后页面上的每一个和服务器交互的操作都要去验证现在的sessionid和数据库里自己用户名对应的sessionid是不是一样,如果一样就说明这个用户名就一个人在登录,一切操作正常,如果不一致说明已经又有人用这个用户名登录了,那现在的这个页面就不能用了,你让它跳转到登陆页面。

这种做法就是最后登录的人有效!!!我们有个项目就是这样作的  但是不知道这样做好不好,如果楼主有什么没有明白的可以再联系我,我一般时都在

#8


引用 4 楼 java2000_net 的回复:
给用户信息增加一个used的标志,
1 每次登录时,将标志更新为 true
2 每次退出登录时,将标志更新为 false;
3 每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了
4 如果不在线,则更新标志为false


有道理,顶一个。

#9


引用 2 楼 little06 的回复:
无非是状态记录而已 
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出 
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除 
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样 
还有一个就是用数据库记录 
也是同一个实现方式


楼主上网找找  单点登陆  咯

就是说的你这个问题

网上应该有很多说这个的,也蛮容易的,偶也想搞,不过现在冒时间,呵呵

#10


acegi有一个concurrent session,设置成1就只能登录一个人咯。

#11


10楼我看过你的看法有点不一样,可以不可以说清楚点啊。还有7楼的,就是用户离开了你怎么处理(比如说点击ie关闭按钮那你怎么处理用户,此时用户已经离线了啊,那怎么处理啊)

#12


Application 里维护一个全局变量就可以了

#13


Application 里维护一个全局变量就可以了,因为Application每个服务器或者web程序职能有一个,在Application范围维护一个全局变量,当第一次登陆就把这个变量置为true,再次登陆判断一下,如果是true就表明已经登陆了一个,就不可以登陆了,很简单吗

#14


明确告诉你,为了你的程序的可用性,你不可能知道用户的准确在线信息。除非你安装插件

比如 flash/applet/activeX

让他们不停的访问服务器,告诉服务器我还活着..... 不过你的服务器得足够好才行。。。

#15


14楼有这种事啊。那就是说,如果一个用户一下线不可能马上知道它下线是否,是不是这个意思啊。我想了解更多点啊。麻烦告诉我,

#16


明确告诉你,为了你的程序的可用性,你不可能知道用户的准确在线信息。除非你安装插件 

比如 flash/applet/activeX 

让他们不停的访问服务器,告诉服务器我还活着..... 不过你的服务器得足够好才行。。。


可不可以说明白点啊。如果一个用户一下线不可能马上知道它下线是否下线,只有通过插件吗。是这样吗。我想了解一下,
可以不可以说明白点啊

#17


很简单 {后来的顶掉前面的}

每个登陆用户有一个SESSION(其中放置登陆用户ID [USERID]) 每个SESSION有一个 SESSION_ID(这个应该是唯一的)

建立一个全局变量字典 
每个新登陆成功的用户 在字典中建立或者覆盖 USERID/SESSION_ID(一个用户登陆第2次 后来的必定覆盖前面的信息)

然后 用户在SERVLET或者JSO执行时 在全局字典中 查询 当前的USERID 获取的SESSION_ID是否是 当前SESSION的SESSION_ID
不一样 就证明已经 被其他地方登陆掉了 则不执行 任何命令

#18


这个问题我曾经弄过

我在blog上写了两篇相关文章,你可以参考一下
《同一时间同一帐号只能登陆一个》
http://heisetoufa.ggblog.com/296626.html

----------------------------------------------------------------

后登陆的用户会把先登陆的用户踢下线

具体实现:sessionCheck:

package test;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionMapping;

public class sessionCheck 
{
 
 private static sessionCheck sessioncheck;
 public sessionCheck(HttpServlet servlet) 
 {
 }
 public static sessionCheck getInstance(HttpServlet servlet) 
 {
  if (sessioncheck==null)
  {
   sessioncheck=new sessionCheck(servlet);
  }
  return sessioncheck;
 } 
 public void setSession(String userName,HttpServlet servlet,HttpSession session,ActionMapping mapping) 
 {
        final ServletContext sc = servlet.getServletContext();//取得容器,容器中根据用户唯一标识userID存放session
        System.out.println(sc);
        System.out.println(session);
        if (sc.getAttribute(userName) != null) 
        {
         // 第二次登陆后第一次无效
            ((HttpSession) sc.getAttribute(userName)).invalidate();// 清除第一次登陆的session
            System.out.println(session);
        }
        sc.setAttribute(userName, session);//放入当前最新session
        mapping.findForward("sessionDestroy") ;
    }

}

UserLoginForm:

sessionCheck.getInstance(this.getServlet()).setSession(userName, servlet, session, mapping);

jsp:

<body ="sessionDestroy()">

< language="java" type="text/java">
sessionDestroy()
{
  alert("连接超时,或帐号已在别处登陆,请查证后重新登陆");
  location.href = "UserLogin.jsp" ;
}
</> 
这样在两台电脑上后登陆的人用户就会把先登陆的给踢掉,但是暂时还没实现在同一台电脑上后登陆的用户把先登陆的踢掉的功能

上面是在后台实现的,如果要在JSP中做,直接appliction.getAttribute(userId),appliction.setAttribute(userId,   session)就行,application的我还没有去测试,有时间去试一下去

#19


在帐号表中加个状态字段,
登录时更改该字段
判断是否被使用

#20


给数据库存储userid的表加一个登陆标志字段,每次登陆进行一下过滤不就行了吗。

#21


每个用户登录都会存下用户的信息,你可以真对这些信息判断,如果为空,就可以登录,如果存在,也就是不为空,你就不能在登录,说明用户正在使用呀,

#22


session有一个监听器,当session销毁时它可以知道。
继承这个监听器,并配置。
在调用时,把用户信息从session中取出,将数据库中对应用户的状态修改。

#23


知道有个东西叫SSO  ,有很多单点登陆的开源产品,也可以自己架设。

可以打通多域名网站 ,也可以控制像你说的那样

#24


引用 2 楼 little06 的回复:
无非是状态记录而已 
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出 
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除 
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样 
还有一个就是用数据库记录 
也是同一个实现方式

#25


其实关键是用户下线判断问题,好象楼上的已经解决了.

#26


你们有自己的看法蛮写上来,没事。我把分数加了100了一共150,写的好的话,多加分。

#27


无非是状态记录而已  
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出  
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除  
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样  
还有一个就是用数据库记录  
也是同一个实现方式 

#28


引用 12 楼 KKK2007 的回复:
Application 里维护一个全局变量就可以了

我觉得这个比较好!

#29


我也做过这样一个项目,我的解决方法是这样的:(相互学习)
建一个用户在线表,用户登陆就判断在线表中是否有此用户,如果有,提示不能重复登陆,没有则成功登陆.
这就要解决用户退出的问题,就是说用户退出删除表中用户的问题.
有几种情况
1,用户点击系统指定退出按钮,系统从数据库中删除在线表中的用户.这个实现很简单就不说了.
2,用户点窗口上的关闭(X)来关闭页面.在JAVASCRIPT里面写一个window.onbeforeunload函数.
window.onbeforeunload = function () {
if (event.clientX > document.body.clientWidth && event.clientY < 0 || event.altKey) {
window.document.forms[0].submit();
alert("\u4f60\u5df2\u5b89\u5168\u9000\u51fa!");
}
}
执行一个form提交,去数据库中删除在线用户.
3,如果用户直接关闭电脑,就是说非正常关机,这个就不好处理了.要用SESSION来判断,如果SESSION失效,则系统自动从数据库中去删除用户,但WEB中的SESSION是服务器端的,不能实时处理用户退出问题,就只有设置SESSION失效时间.
写一个Listener继承HttpSessionListener在sessionDestroyed()方法中执行数据库删除操作.


以上基本可以满足一般系统要求,当然还有一点就是,当服务器启动则执行在线表的清空操作.客户不喜欢每次重启服务器都要手工去表中删除未清空的在线用户.
写一个SERVLET让其在容器启时自动启动,设置WEB.XML中的<load-on-startup>为一数字即可.
还有什么没有写到的地方望大家赐教.

#30


不好意思,刚才是从代码中拷的.
那个ALERT("")里面的意思是"您已安全退出!"

#31


1、状态记录意义不大,因为HTTP本质上是无状态的,你不知道谁在线,因此只能实现后面的有效登入踢掉前面的登入,那么,所谓的后面和前面需要更多的信息来判断,仅仅一个状态毫无意义,一般的处理是以登入机器的特征,比如IP,Cookie等的演算,判断新的登入与先前的登入演算码是否一致
2、由上,新的登入之后,最节省识别方式可能是在浏览器和WEB Svr 之间互通一个登入随机数(新登入时产生),该数可以存储在任何合理的地方,传输通道最合理的应该是session cookie,也可以是请求参数

#32


这个问题我也曾经碰到过,有人说加个字段来标识是否登录,也有人用HashTable来存,还有人用监听器来监听SESSION,更有人让服务器每秒刷新来判断SESSION是否还存活……
但这些方法都不能完全解决你的问题。因为,如果遇到突然断电或者直接关闭浏览器窗口之类的事件,不仅不会更改数据库,更不会被监听到...

其实我也是说大话,至今也不知道解决的好办法。
不过,一般的WEB程序要求都不至于这样严格,把密码之类的安全性做高点就OK了

#33


我只是接分來的。。。。

#34


一起来建设我们的Software   Coffee   House(SCH) 
CSDN群 招募中……

#35


这个问题也真的是不怎么好回答。
我也只学JSP一个月
我个人的观点
JSP不是有COOKIE的功能吗。
不能说是功能,
如果他登陆 我可以更新他的
以下借用的啊:
给用户信息增加一个used的标志, 
1 每次登录时,将标志更新为 true 
2 每次退出登录时,将标志更新为 false; 
3 如果不在线,则更新标志为false 
以下自己的观点:
如果他点浏览器关闭 我会话肯定不是原来的了
但是我可以用过滤器过滤 得到他的COOKIE中保存的信息 进行验证
为TRUE的话 我可以给他创建会话。
当他点退出的时候
我可以把他COOKIE的内容给销毁掉
不知道是不是答非所问了

#36


还有会话。

#37


关注ing!

#38


HTTP的特性决定不可能完全准确的判断用户何时离线。所以不现实也没必要精确地刷新在线的用户信息,有一定的时间冷却是可以接受的。而冷却时间要看你的服务器了。

#39


其实,那些说容易的人根本就连楼主的问题都没有搞明白

最本质的原因在于http协议在一定能够的程度上可以说是一种残疾的协议
只能由客服端单纯的“拉”取数据,而不能想像tcp/ip一样实现三次握手
服务端也不能“推”数据,他是一种无状态的协议,,我们很难判别浏览器
在什么时候推出,异常的结束会话!这也是问题的关系!
acegi我还没有研究过,
但是我有种思路就是
1)设置用户合法注销,给出链接,至于是去在数据库还是application里面加状态字,随情况定
2)用户点击关闭按钮的时候,发送ajax请求,请求后端注销账号
但是,不能应付用户在任务管理器种关闭进程的方式
期望高手给出完美解决方案

#40


ls的这么多解决方案还不能解决你的问题吗?

如果服务器好的话,用session比较简单


或者用插件。

#41


补充一下
如果服务器足够健壮的话
我们可以考虑在客服端设置一个一定时间间隔的触发器
每次都像后台发送“userid”这个字段,后台可以根据time>时间间隔
的情况判断用户是否”生存“,加控件的话,不好的地方在于我们大多数要求
我们的程序能够跨越浏览器生存

#42


在JAVA中,你能用SESSION来判断,SESSION在登陆的时候,会监听到新SESSION的创建,这样,你可以用ARRAYLIST来保存这个登陆成功的用户ID,SESSION设置超时1小时清除。
如果有人在其他地方登陆,那么首先读ARRAYLIST保存的用户ID,如果ID存在,则证明此ID已被他人登陆中,提示不能重复登陆。
具体代码:

public class User implements HttpSessionBindingListener {

   private int userid;
//GETTS,SETTS METHODS ADD IN HERE
public void valueBound(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
System.out.println("add some one");
System.out.println("userid:"+userid);
boolean isExists=userList.contains(Integer.toString(userid));
if(isExists==false)
userList.addUser(Integer.toString(userid));
}


public void valueUnbound(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
System.out.println("remove some one");
System.out.println("userid:"+userid);
boolean isExists=userList.contains(Integer.toString(userid));
if(isExists==true)
userList.removeUser(Integer.toString(userid));
}
}


完整代码比较长,要涉及你的登陆系统怎么来做的,但上面是最关键核心的代码,结合我的描述,你实现出来应该不难

#43


引用 42 楼 cchaha 的回复:
在JAVA中,你能用SESSION来判断,SESSION在登陆的时候,会监听到新SESSION的创建,这样,你可以用ARRAYLIST来保存这个登陆成功的用户ID,SESSION设置超时1小时清除。 
如果有人在其他地方登陆,那么首先读ARRAYLIST保存的用户ID,如果ID存在,则证明此ID已被他人登陆中,提示不能重复登陆。 
具体代码: 

Java code
public class User implements HttpSessionBindingListener {

   private int userid;
//GETTS,SETTS …


瞎激情;
关键问题在于我们是否可以尽量的缩短你的这个一小时时间差,我加入在这一小时之间登陆的时候,
那且不是要等待一个小时;

所以,这里的发言2/3可以完全过滤掉!

#44


是个比较麻烦的事情,用新的顶掉旧的应该不错,关注

#45


个人感觉新的定旧的不错,新登入的直接覆盖掉旧的,至于旧的请求可以根据sessionID来判断是不是最新,不是就提示,并要求重新登入。这样感觉是最简单的。

还有就是旧的不能顶新的,上面已经有很多人提供方法了,关键就是退出的问题,其实没有必要管理这个退出,只要当前判断当前用户正在使用(方法上面已经说了很多了),就不让新的用户登陆就是,然后在设置一个选项,强制登陆,在强制登陆的情况下 ,就会覆盖掉旧的。这样应该能适合一些情况吧。或者加个选项不允许强制登陆,使强制登陆失效,但这样情况下,可以为系统设置一个检测时间,如:30分钟内该用户没有响应就自动掉线,或者失效。这2个方法结合应该能稍微能改善点吧

#46


假设用户A先使用帐号s登陆,用户B后使用帐号s登陆。
处理情况分两种:
一、不允许B登陆
  1、数据库创建标记位。
  2、创建map表存储userName-->sessionId。
  两种方法,缺点:当用户A在未正常退出---session失效的时间内,帐号s无法使用。即使可以监听到用户关闭浏览器,也无法监听到用户从任务管理器关闭浏览器、
                  浏览器错误甚至机器断电。所以不建议使用此方法。

二、踢掉用户A
  1、数据库记录sessionId。
  2、创建map表存储userName-->sessionId。
  原理:以map表为例,当用户A登陆时,读取userName对应的sessionId,如果存在则覆盖之,不存在,则添加到map表,map表数据如:s-->sessionIdA.
        当用户B登陆时,做同样操作,map表数据如:s-->seesionIdB。当A再次发出请求时(非登陆请求),读取userName对应的sessionId,
        sessionIdA(A的请求携带的)!=sessionIdB(map表中读取的),设置sessionIdA无效,跳回登陆页,要求登陆。
        只需要建一个filter过滤登陆请求,一个filter过滤非登陆请求。

#47


请求走的本来就是无状态协议
如果想做的实时精度高的
看看server push
http://topic.csdn.net/t/20000704/10/13930.html
不断线,服务端向客户端推的技术吧

#48


引用 5 楼 wlj11111 的回复:
每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了 
我就有了一个疑问了,那就是如果一个用户下线了,然后马上登录,那就不可能登陆啊,要等到一段时间才能登录。这样的话就成了问题了啊


可以使用Session啊,登录了就记在Session中,下次有用户登录就与Session中存的比较,有相同的就不允许登录,否则就可以登录
用户一退出就马上注销Session,这样就不存在这样的问题了

#49


引用 48 楼 import_jsp 的回复:
引用 5 楼 wlj11111 的回复:
每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了  
我就有了一个疑问了,那就是如果一个用户下线了,然后马上登录,那就不可能登陆啊,要等到一段时间才能登录。这样的话就成了问题了啊 
 

可以使用Session啊,登录了就记在Session中,下次有用户登录就与Session中存的比较,有相同的就不允许登录,否则就可以登录 
用户一退出就马上注销Session,这样就不存…


这位仁兄貌似有点没搞清楚状况,站着说话不腰疼,知道大家都在讨论什么不
用户一退出就马上注销session,你以为在玩c/s呢

#50


明天结贴还有谁有自己的看法的啊,蛮写上来吧。