限制多窗口重复登陆
我们都知道WEB服务器通过识别客户请求中的session id来判断是否返回新的HttpSession,一般情况下这个session ID是保存在客户端cookie中,准确的说是保存在session cookie中。 也就是说一旦关闭浏览器,此session cookie消失,保存其中的session ID也随之消失。再新建的浏览器再次发起请求时,服务器端找不到对应的session ID就会新建一个HttpSession返回给客户。
现在要求系统防止用户短时间内多次发起同一请求给APP造成业务处理压力,于是在用户登陆后第一次发起此请求时记录当前时间保存到Session中,并且在下次发起相同请求时从Session中去除上次请求时间计算时间差,小于5min时给出提示并驳回请求。但是因为存在上述的问题,聪明(还是狡猾的?)客户利用多次开关浏览器便可以突破这个限制。我现在在想是否能将session ID保存到客户端硬盘的cookie上,即cookie.setMaxAge(N); N>0的方法。但是貌似session ID不能保存到持久化cookie上,不知道各位有没有什么办法?
另外,如果能顺利地将session ID保存到持久化cookie上,会出现另外一个问题。不同用户在同一台pc上登陆系统,却发送相同的session ID给服务器,显然不对。因此,得让存在持久化cookie上的session ID根据系统登陆用户不同而不同,这需要在把cookie放到HTTP HEAD之前,拿到session ID并根据当前登陆用户做处理。不过对cookie的处理是在服务器端执行reqeust.getSession()的时候直接去cookie中的JSESSIONID属性,我怎么
才能让cookie中保存多个JSESSIONID呢
顺便提一下,我们生产环境上4台WEB SERVER,配置了Session共享和session粘性,即对客户来说,就跟只有一台WEB一样。另外,我们有SSO,但是cookie.setMaxAge(-1);于是跨浏览器的话Session又是新的了
case0079 写道URL REWRITE
URL REWRITE前提是服务器端给返回一个JSESSIONID,但如果客户端给过去的jsessionid每次都不同,如何指望返回来的东东的正确性呢。
同上,棘手的不是server side,而是client side
凤舞凰扬 写道引用好像服务器就是根据session id来判断是否是同一个用户的,如果是一有的seesion id,则会将请求分流到之前处理这个请求的节点上。现在的问题是session id在每次IE关掉之后在客户端都没有了,服务器没办法进行识别。
不知道我的理解是否正确
我们常说的session id是服务器判断与之相连接的客户端的会话,实质上,和我们另外一个角度理解的用户是有区别的。你说的没错,如果已经存在session,就转发。不过后面一句就陷进去了。其实我前面说过,你需要传递另外一个东西,jsessionId,你在很多网站都可以看到这种应用(尤其是IBM的),对于转发服务器来说,是否存在http session并不重要,没有创建一个就是。你session中存储的数据并不在其中,而是在你对应的JVM节点中,而它是可以通过jsessionId这样的方式去获取的。
至于说怎么识别这样的东西,其实所有的支持负载均衡多个JVM节点并存的服务器都支持。或者大不了如楼上所说,自己建立中央缓存,自己在程序中识别这样的request参数。
大概明白您的意思了。即把session id存放在JVM SESSION中而非HTTP SESSION中,跟之前那位兄弟提到的memcache方案基本相似。但关键是,这个seesion id在第一次被HttpSession返回来后,如果想在下次发起请求是将其原样送给服务器,就必须有一个机制在客户端能让其存活下来,而以浏览器为单位的session cookie是做不到的。
也就是说,问题的关键不是服务器端没办法识别jsessionid,而是这个jsessionid在客户端没法持久化。除非...我能通过在客户端JS上自己动手伪造一个跟登录客户ID相关的jsessionid出来
31 楼 GeassLei 2009-12-26 自己写一个单例程序
里面拿着所有的session的引用,当session销毁里也把引用删除掉。当新的用户登录里,就用session里面存储的username(在表里是唯一的那个)来比较是否用户已经登录了。 32 楼 GeassLei 2009-12-26 spring security里也有一个防止重复登录的过滤器,楼主可以参考一下,实现方法去上面所说的大概相同 33 楼 Joo 2009-12-26 凤舞凰扬 写道引用好像服务器就是根据session id来判断是否是同一个用户的,如果是一有的seesion id,则会将请求分流到之前处理这个请求的节点上。现在的问题是session id在每次IE关掉之后在客户端都没有了,服务器没办法进行识别。
不知道我的理解是否正确
我们常说的session id是服务器判断与之相连接的客户端的会话,实质上,和我们另外一个角度理解的用户是有区别的。你说的没错,如果已经存在session,就转发。不过后面一句就陷进去了。其实我前面说过,你需要传递另外一个东西,jsessionId,你在很多网站都可以看到这种应用(尤其是IBM的),对于转发服务器来说,是否存在http session并不重要,没有创建一个就是。你session中存储的数据并不在其中,而是在你对应的JVM节点中,而它是可以通过jsessionId这样的方式去获取的。
至于说怎么识别这样的东西,其实所有的支持负载均衡多个JVM节点并存的服务器都支持。或者大不了如楼上所说,自己建立中央缓存,自己在程序中识别这样的request参数。
大概明白您的意思了。即把session id存放在JVM SESSION中而非HTTP SESSION中,跟之前那位兄弟提到的memcache方案基本相似。但关键是,这个seesion id在第一次被HttpSession返回来后,如果想在下次发起请求是将其原样送给服务器,就必须有一个机制在客户端能让其存活下来,而以浏览器为单位的session cookie是做不到的。
也就是说,问题的关键不是服务器端没办法识别jsessionid,而是这个jsessionid在客户端没法持久化。除非...我能通过在客户端JS上自己动手伪造一个跟登录客户ID相关的jsessionid出来
case0079 写道URL REWRITE
URL REWRITE前提是服务器端给返回一个JSESSIONID,但如果客户端给过去的jsessionid每次都不同,如何指望返回来的东东的正确性呢。
同上,棘手的不是server side,而是client side
GeassLei 写道spring security里也有一个防止重复登录的过滤器,楼主可以参考一下,实现方法去上面所说的大概相同
这个之前有兄弟提到过,正在研究中,谢谢提醒 34 楼 nishizhutou 2009-12-27 将业务bizID合并为一个参数存到cookie中.
如:biz.username=bizID;
然后页面提交的时候找到当前username对应的bizID,将其传回来.
服务端建立userName和bizID以及IP的对应关系. 35 楼 xieke 2009-12-27 请参见这个老帖子:
http://www.javayou.com/diary/8534 36 楼 Joo 2009-12-27 最后还是来总结一下吧,就是自造JESSIONID和memcache结合来搞定 37 楼 ebeach 2009-12-27 参见 http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpSessionBindingListener.html
javax.servlet.http.HttpSessionBindingListener
valueBound(HttpSessionBindingEvent event);
valueUnbound(HttpSessionBindingEvent event);
借助Session监听可以完成你要的功能。 38 楼 522656914 2009-12-28 浏览器的关闭时间应该可以捕获吧,我在校内网上写日志的时候传了照片,在日志没写完的时候我不想写了,就关了浏览器,这时竟然弹出一个对话框问我是否放弃本次日志,点击确定后提交了表单才关闭的。 39 楼 ywlqi 2009-12-28 感觉楼主被JSESSIONID给绕进去了,其实就像前面兄弟说的在数据库增加上次登录时间一个字段完全可以解决问题
另外楼主用了SSO,在SSO server端也可以解决问题,当然如果sso server也是多机配置的话同样要注意session 共享的问题
个人认为用数据库是最简单的解决方案 40 楼 redwatch 2009-12-28 其实很简单
你在客户端浏览器用AJAX每隔一段一时间对服务器进行一交请求(如:每秒一次)
如果发现在这个session 之后还有同一个用户登陆,注消前一个session ,旧session客户端浏览器页面退出(有果还没有关闭),用最新的session
返正服务器端能保留一个用户一个session(一一对应),在每增加session前检查该用户有没有登陆 41 楼 lydawen 2009-12-28 kunee 写道说来说去不就是少了个记录的地方吗
数据库是干什么用的
在高并发的场景下少查数据库(I/O)才是最终需要做到的 42 楼 vvggsky 2009-12-28 引用 我现在在想是否能将session ID保存到客户端硬盘的cookie上,即cookie.setMaxAge(N); N>0的方法。但是貌似session ID不能保存到持久化cookie上,不知道各位有没有什么办法?
通常session是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的sessionid,这样我们信息共享的目的就达不到了,我们可以先把sessionid保存在cookie中,然后在新窗口中读出来,就可以得到上一个窗口SessionID了,这样通过结合JSESSIONID 这个cookie来实现跨浏览器访问。 43 楼 Joo 2009-12-28 redwatch 写道其实很简单
你在客户端浏览器用AJAX每隔一段一时间对服务器进行一交请求(如:每秒一次)
如果发现在这个session 之后还有同一个用户登陆,注消前一个session ,旧session客户端浏览器页面退出(有果还没有关闭),用最新的session
返正服务器端能保留一个用户一个session(一一对应),在每增加session前检查该用户有没有登陆
貌似这样做的压力也小不了
我们现在已经在组织研讨设计新UM架构,包括SSO的设计也可能redesign,建设跨HttpSession的缓存机制势在必行
既然不用HttpSession了,也就没必要一定要挂在JSESSIONID这棵树上吊死 44 楼 ywlqi 2009-12-28 lydawen 写道kunee 写道说来说去不就是少了个记录的地方吗
数据库是干什么用的
在高并发的场景下少查数据库(I/O)才是最终需要做到的
原则是对的,但只是在用户登录时做一下我认为代价还是允许的
论坛是很典型的例子,论坛的访问量够大吧,论坛都做用户上次登录时间记录,我相信绝大部分应用这样做应该不是问题
45 楼 wanglei1314520 2009-12-29 我的思路:
在用户表里增加三个字段:登陆时间、session标识、登陆标识(0,1)
用户登陆时如果登陆标识为0(未登录),则把登陆时间、sessionid保存db中并设置登陆标识为1
用户登陆时如果登陆标识为1(已登录),则取db中的登陆时间与当前时间做差,如果小于5min则提示不能登陆(如果想把之前登陆的T掉,可以在用户登陆时把sessionid和session对象保存在application中,当用户登陆时如果登陆标识为1,则从db中取登陆用户的sessionid,根据此sessionid从application中取得session对象并销毁)
-----------------------------
在项目里加个session监听,当session销毁事件触发时,取得销毁的sessionid,并把db中对应记录的登录标识改为0 46 楼 Joo 2009-12-31 this is what i am looking for
http://www.iteye.com/topic/135066
http://www.iteye.com/topic/551498 47 楼 gavin.zheng 2010-01-01 非常简单的解决方法,使用cookie技术:
在服务器上作一个filter, 获得当前jsession内容,然后新建个cookie 假设为dsession 把jsession+当前time 组合编码 保存到client, 此cookie保存时间为 5分钟
1, 假设新开游览器在5分钟内, 则存在dsession ,那么的话,client可以知道判断出对方不可以使用此功能,
2, 如果在5分钟外,则不存在 ,则新建dsession 48 楼 gavin.zheng 2010-01-01 忘记说了, 那个dsession保存的部分上次session串是用来比较是否是新开游览器的
49 楼 hhww0101 2010-09-08 可以考虑使用Application,还可以防止客户多浏览器登录,或者同一帐号,同时多次登录。 50 楼 angelbear220 2010-09-19 1.登录页面-------》登录-------》根据用户名读取登录记录表-------》存在有效的session转步骤2-----》保存登录用户名及对应的sessionID到登录记录表---》进行其他操作。
2.该用户当前有效的session存在-----》提示用户上次登录未正常退出----》方案一:将上次session失效,给本次登录重启一个session。方案二(没试过):用从数据库中原sessionId重写客户端的sessionId,以恢复上次会话。----》进行其他操作