关于这个问题,我也看了很多的帖子,但是,基本都是那种零零散散的,不知道那位高手对这种有何看法。如果好的话,我还会加分,再100分。希望高手踊跃发言啊。
解决方案 »
- 自动生成jsp
- java程序员成长之路
- 在jsp中设置一个文件上传框怎么弄?
- myeclipse部署网页乱码
- 跪求:[Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket.
- jsp用了bean后显示乱码,在线等解决!!!!!!!!!!!
- JSP如何将查询出来的数据导入到excel表格中
- setAttribute的小问题,弱弱的问
- 新手问题!!!急~!在线等!!!
- 请求用递归创建菜单树(急用)
- 用户注册后,跳转到首页,把原来在哪的登陆的表单隐藏,在那里显示用户名怎么搞,
- unexpected token: * near line 1, column 8 [select * form com.user]
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样
还有一个就是用数据库记录
也是同一个实现方式
在session过期时把该用户帐号从ServletContext中删除,注意一下并发访问
1 每次登录时,将标志更新为 true
2 每次退出登录时,将标志更新为 false;
3 每隔一段时间(比如10分钟)查看用户是否在线? 具体怎么判断,那是另一个讨论话题了
4 如果不在线,则更新标志为false
可以不可以说明白点啊
每个新登陆成功的用户 在字典中建立或者覆盖 USERID/SESSION_ID(一个用户登陆第2次 后来的必定覆盖前面的信息)然后 用户在SERVLET或者JSO执行时 在全局字典中 查询 当前的USERID 获取的SESSION_ID是否是 当前SESSION的SESSION_ID
不一样 就证明已经 被其他地方登陆掉了 则不执行 任何命令
《同一时间同一帐号只能登陆一个》
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的我还没有去测试,有时间去试一下去
继承这个监听器,并配置。
在调用时,把用户信息从session中取出,将数据库中对应用户的状态修改。
一,把Session的状态记录下来(内存),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行内存移出
二,把Session的状态记录下来(文件),如登陆为1,未登陆为0,然后在每人登陆的时候进行判断,下线的时候也进行判断,文件清除
上面都需要用到Session监听器,你可以看看统计在线人数怎么做的,其实原理一样
还有一个就是用数据库记录
也是同一个实现方式
建一个用户在线表,用户登陆就判断在线表中是否有此用户,如果有,提示不能重复登陆,没有则成功登陆.
这就要解决用户退出的问题,就是说用户退出删除表中用户的问题.
有几种情况
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>为一数字即可.
还有什么没有写到的地方望大家赐教.
那个ALERT("")里面的意思是"您已安全退出!"
2、由上,新的登入之后,最节省识别方式可能是在浏览器和WEB Svr 之间互通一个登入随机数(新登入时产生),该数可以存储在任何合理的地方,传输通道最合理的应该是session cookie,也可以是请求参数
但这些方法都不能完全解决你的问题。因为,如果遇到突然断电或者直接关闭浏览器窗口之类的事件,不仅不会更改数据库,更不会被监听到...其实我也是说大话,至今也不知道解决的好办法。
不过,一般的WEB程序要求都不至于这样严格,把密码之类的安全性做高点就OK了
CSDN群 招募中……
我也只学JSP一个月
我个人的观点
JSP不是有COOKIE的功能吗。
不能说是功能,
如果他登陆 我可以更新他的
以下借用的啊:
给用户信息增加一个used的标志,
1 每次登录时,将标志更新为 true
2 每次退出登录时,将标志更新为 false;
3 如果不在线,则更新标志为false
以下自己的观点:
如果他点浏览器关闭 我会话肯定不是原来的了
但是我可以用过滤器过滤 得到他的COOKIE中保存的信息 进行验证
为TRUE的话 我可以给他创建会话。
当他点退出的时候
我可以把他COOKIE的内容给销毁掉
不知道是不是答非所问了
只能由客服端单纯的“拉”取数据,而不能想像tcp/ip一样实现三次握手
服务端也不能“推”数据,他是一种无状态的协议,,我们很难判别浏览器
在什么时候推出,异常的结束会话!这也是问题的关系!
acegi我还没有研究过,
但是我有种思路就是
1)设置用户合法注销,给出链接,至于是去在数据库还是application里面加状态字,随情况定
2)用户点击关闭按钮的时候,发送ajax请求,请求后端注销账号
但是,不能应付用户在任务管理器种关闭进程的方式
期望高手给出完美解决方案
或者用插件。
如果服务器足够健壮的话
我们可以考虑在客服端设置一个一定时间间隔的触发器
每次都像后台发送“userid”这个字段,后台可以根据time>时间间隔
的情况判断用户是否”生存“,加控件的话,不好的地方在于我们大多数要求
我们的程序能够跨越浏览器生存
如果有人在其他地方登陆,那么首先读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));
}
}
完整代码比较长,要涉及你的登陆系统怎么来做的,但上面是最关键核心的代码,结合我的描述,你实现出来应该不难
处理情况分两种:
一、不允许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过滤非登陆请求。
如果想做的实时精度高的
看看server push
http://topic.csdn.net/t/20000704/10/13930.html
不断线,服务端向客户端推的技术吧
可以使用Session啊,登录了就记在Session中,下次有用户登录就与Session中存的比较,有相同的就不允许登录,否则就可以登录
用户一退出就马上注销Session,这样就不存在这样的问题了
这位仁兄貌似有点没搞清楚状况,站着说话不腰疼,知道大家都在讨论什么不
用户一退出就马上注销session,你以为在玩c/s呢
46楼分析的很有道理第一种情况的实现是:
1.当用户访问该登陆页时Session建立,当用户登陆后我们才知道此帐号UserID
2.这时我们可以在登陆的逻辑代码中 将Session和UserID 一并保存到Application或SverletContext的在线用户列表当中.
(这里如果用Session监听器HttpSessionListener是不行的,只能用HttpSessionBindingListener在登陆时绑定监听)
3.当其他用户B使用此帐号登陆时 就可以查找用户列表中是否有UserID 有则将B用户转向失败提示页面。
4.当Session销毁时 将Session和UserID 从Application或SverletContext的用户列表当中移除。
上面所谈到的缺点也正式这两种Session监听器,在监听Session销毁时的一个弱点
HttpSessionListener两种情况下执行sessionDestroyed(HttpSessionEvent e)(会话销毁)
1:执行session.invalidate()方法时。
2:如果用户长时间没有访问服务器,超过了会话最大超时时间,服务器就会自动销毁超时的session。
倘是第一种情况 一般是属于正常session销毁,而第二种则是属于非正常销毁 要等待一段时间,session超时销毁。而这段时间此UserID 其他用户无法再登陆。
HttpSessionBindingListener三种情况下执行valueUnbound(HttpSessionBindingEvent e)
1.2相同。
3:执行session.setAttribute("Listener", "其他对象");或session.removeAttribute("Listener");将listener从session中删除时。
所以不够理想。二、踢掉用户A 1.当用户访问该登陆页时Session建立,当用户登陆后我们才知道此帐号UserID
2.这时我们可以在登陆的逻辑代码中 将Session和UserID 一并保存到Application或SverletContext的在线用户列表当中.
(这里如果用Session监听器HttpSessionListener是不行的,只能用HttpSessionBindingListener在登陆时绑定监听)
3.当其他用户B使用此帐号登陆时 就可以查找用户列表中是否有UserID 有则将B用户Session和UserID替换掉原有的ID。
4.当Session销毁时 将Session和UserID 从Application或SverletContext的用户列表当中移除。
三 两种Session监听器的比较 1.绑定方式上不同 : HttpSessionListener发挥作用,我们将它添加到web.xml中,只需要设置到web.xml中就可以监听整个应用中的所有session。
<listener>
<listener-class>pkg.xxxxListener</listener-class>
</listener>
而HttpSessionBindingListener发挥作用,必须实例化后放入某一个session中,才可以进行监听。如在登陆时候:
session.setAttribute("xxxxxBindingListener", new xxxxxxxBindingListener(userID));
HttpSessionBindingListener通常都是一对一.正是这种区别成就了HttpSessionBindingListener的优势,我们可以让每个listener对应一个userID,这样就不需要每次再去session中读取userID,进一步可以将所有操作在线列表的代码都移入listener,更容易维护。
2.销毁方式刚讲过了! 3.两个不同的接口实现。
你可以到網上去下載相關資料,在網上找不到的Q我,我這里有,這兩天兒我也開始學習它
就是检查用户是否在线麻烦!!
session机制不太好!!用户直接关闭浏览器session不能自动取消!!还得等session到期!!
面有这个用户存在就不让登录。登出时remove掉这个用户。在登出及点击ie X时remove用户。在监听器监听到session失效时
也remove。后来只有一个问题没解决,就是在ie url地址栏直接输入地址,然后转向这个事件捕捉不到。
2 要是关闭浏览器得话,就麻烦点了。怎么监听关闭浏览器呢,先看看关闭方法:直接点击关闭、任务栏中关闭、任务管理器中关闭,用什么来监听好呢,unload方法肯定不行了,这样页面就不能刷新了。
3 断电,这是最麻烦的。以上的方案恐怕都不行了,要是把状态写到数据库里。那用户在修改数据库之前永远不能登陆了。写到集合里,也是不能登陆,应该等到web服务器重启,这样也不太好。基本上很少重启。如果后登陆的踢掉先登录的,那后登陆的要是非法用户不麻烦了。你得在登陆了,要是有重要信息的话,你们两个就需要不断的互相踢出登陆了。如果写个监听器,那倒是好,放到哪都无所谓了,但就是耗费多点服务器资源。如果这个单点登陆非做不可的话,那我感觉最好的是:把用户信息写到list里或者写到数据库里,再写个监听程序,放在服务器上定时监听30秒(自己视情况而定)执行一次把非正常退出的用户信息删除。java里面有timerTask,用它吧。或者自己写线程控制也行。我前些天也打算做这个来着,但是碍于我们开发的系统安全性没这么高,做起来又繁琐,就放弃了这种方案。