问题描述:IE7不同选项卡选择不同的用户对同一个Web应用进行登录,服务器跟踪堆栈时发现两个用户所用的session会话都是一样的。

初步诊断:初步判断为IE7不同选项卡属于同一个进程,由于默认开启了cookie来跟踪会话,服务器端会默认收到客户端http请求中传过来的cookie中的session id,并为这些不同的用户都分配同一个session会话。由于该Web应用中没有使用URL重写,在tomcat下禁用cookie会影响正常功能。请问各位有没有遇到过类似的问题,有什么好的解决方案吗?谢谢!
评论
blowfisher 2007-08-22
问题的根源是浏览器的"TAB机制"引起的,
治本的满足客户的“需求”,应该动浏览器,而不是动设计。。定制一个浏览器,修改共享Session的"TAB机制",这样一劳永逸
jianfeng008cn 2007-07-22
总结下解决办法:

1一种,在后台使用单session针对一个机器(IP),然后通过唯一性标识绑定用户 进行区分,
类似在session中放一个Map<userid,Map<sessionKey,sessionValue>>

2另外一种思路我觉得更好,在client的页面上 设置hidden input 将seesionId携带,或者url携带sessionid,这样的好处是服务器不需要做改变,问题是client只有最后操作的用户的cookie使用上要更小心,会覆盖别的用户的cookie信息

3另外大家还提到了泛域名的方法,这个如果实现方便的话,应该是最好的吧


ps:
以前用dotnet的时候我们系统采用了类似2的方式,实现了多用户登陆的,运行良好。
很多同学不好好看贴,翻来覆去地不知道要搞什么,浪费时间。
总结如有问题请指正,谢谢。
janh 2007-07-20
flxi78 写道
看来原理决定了实在没有简介的解决方案啊。
不过第一种解决方案,还能有简单的方式么?这样的话要重构的地方实在太多了,要是我,肯定受不了


如果能改变web服务器的sessionid传递机制倒是能简单一点,比如不用cookie,把sessionid放在url跟的参数中,能实现一个用户一个session,即使这样,每个页面中的所有url都要加上这个sessionid也比较麻烦。
flxi78 2007-07-20
看来原理决定了实在没有简介的解决方案啊。
不过第一种解决方案,还能有简单的方式么?这样的话要重构的地方实在太多了,要是我,肯定受不了
janh 2007-07-20
基于这样一种考虑:
在同一窗口的不同页签中用相同的url(包括后面的参数)运行出不同的结果来是不可能的,因为他们发到后台的信息是完全一样的,相同的sessionid传递机制sessionid也相同。

那么要实现多页签登录多用户,只有用不同的url来实现。
有两种方法,一种是在url后面加上用户的参数,如?userid=ed3432432,每个url不管是post还是get方式都要加,后台要实现在一个session中能够管理多个用户的登录。还有个问题,就是多个用户共用cookie,因此不能正常使用cookie。

另一种方法是修改url中的域名部分,如javaeye中blog的域名:janh.javaeye.com,实现泛域名解析,这种方式实际上每个用户的sessionid是不同的,因为sessionid的传递机制用cookie是识别域名的,不同的域名使用不同的cookie,因此每个用户得到是不同的session。

多个用户中每个用户打开多个页签也不会混淆,因为每个用户的域名是一样的,用的cookie也是一样的,在cookie中保存的其他信息也不会混淆。

在实现上,程序的处理上不用做任何改变,唯一要做的是在用户登录后重定向到他的域名地址,或者在登录页面根据输入的用户名直接登录相应的域名,后面的各个页面请求自动转到这个域名了,包括弹出的子页签也是跟的这个域名,但是要注意在页面的各个url链接中不要写全路径,只写域名后面的部分就行了,一般也都是这么写的吧。

实际上像阿里巴巴购物、网易邮箱都是用泛域名来做的。

另:实现泛域名解析只要在域名服务器上设置一项: *.javaeye.com 指向61.152.145.77 就可以了。
fins 2007-07-20
lee5593 写道
flxi78 写道
如果上面的问题解决了,那用户再打开一个tab,并且在地址栏里输入URL地址访问某个特别的页面,怎么办?是显示还是拒绝?如果显示,显示谁的?

一直以来我没有逆向去思考过这个问题,flxi78的疑问应该解释了浏览器为什么不支持多选项卡多用户会话跟踪的原因,如果是这样的话,那我们应该讨论的问题就是怎样防止用户利用不同选项卡进行多用户登陆以规避该设计带来的潜在的风险,各位的看法如何?


实际上如果采用"禁止用户在ctrl+n 或ctrl+t 打开的窗口里进行多用户登录操作"这样的方式,那问题就简单得多了.

通过很多技巧都能实现.但是我们的客户明确的说了"我们要用,你们的系统如果不支持,是你们的问题".

实际上 多用户登录这一情况是正常的(一个人有多帐号 多权限很正常),而使用ctrl+n 或ctrl+t等快捷键能够提高工作效率 而且符合用户习惯,这也是无可厚非的,所以我们很难采用"禁止客户...."的策略啊
fins 2007-07-20
貌似行不通吧.

因为原窗口,和你在新的选项卡里打开的窗口共用一套cookie.
你对"对cookies进行修修补补",这样的话会影响到原窗口吧.

我也一直在研究这方面的问题.
我们的系统都上线了才被告知 客户需要在 ctrl+n 或者ctrl+t打开的窗口里换用户登录,同时保证已经打开的窗口登录信息不丢失.

其实要是早知道这样,当初就把session内的登录信息设置成支持多帐号的就好了,唉.事后补救似乎真的没有很好的办法啊.

继续关注
flxi78 2007-07-19
有人喜欢吃菜,有人喜欢吃肉,个人有个人的爱好。我觉得这本身不是BUG,所以也不用防止用户利用不同选项卡进行多用户登陆以规避该设计带来的潜在的风险。就我个人的开发经验就碰到过一次,客户要求在新打开一个TAB这样的情况,就用原来的用户数据自动登录的。所以我们只要知道浏览器有这个特性,以后开发时注意就好了。
到是楼主的问题,假设真的有楼主这样的需求,客户说要改,怎么办?我们该怎么用最小的代价来对应用进行重构?
如果我们能够把强制tomcat设置成通过URL中携带JsessionID的方式,那可以解决楼主的问题,但是楼主说应用不能关闭cookie,否则就运行有问题,那我们换个思路,强制tomcat设置成通过cookie的方式来携带JsessionID.然后做一个Filter,该filter会对每一个request进行检查:
String retUrl = request.getHeader("Referer");
通过这个方式获取request的上一个请求url,如果是null,就说明该请求是新页面访问(一个新的TAB),
if(用户请求URL是Login.jsp&&retUrl==null){
request.getCookies,然后对cookies进行修修补补,再来个URL重定向什么的.
}else if(用户请求URL不是Login.jsp&&retUrl==null){
  那不让他访问
}else{
该怎么着还怎么着.
}
这个方法是我的不成熟的想法,我也没有测试或者验证过,特别是:request.getCookies,然后对cookies进行修修补补,再来个URL重定向什么的.不知道行不行的通?
flxi78 2007-07-19
有人喜欢吃菜,有人喜欢吃肉,个人有个人的爱好。我觉得这本身不是BUG,所以也不用防止用户利用不同选项卡进行多用户登陆以规避该设计带来的潜在的风险。就我个人的开发经验就碰到过一次,客户要求在新打开一个TAB这样的情况,就用原来的用户数据自动登录的。所以我们只要知道浏览器有这个特性,以后开发时注意就好了。
到是楼主的问题,假设真的有楼主这样的需求,客户说要改,怎么办?我们该怎么用最小的代价来对应用进行重构?
如果我们能够把强制tomcat设置成通过URL中携带JsessionID的方式,那可以解决楼主的问题,但是楼主说应用不能关闭cookie,否则就运行有问题,那我们换个思路,强制tomcat设置成通过cookie的方式来携带JsessionID.然后做一个Filter,该filter会对每一个request进行检查:
String retUrl = request.getHeader("Referer");
通过这个方式获取request的上一个请求url,如果是null,就说明该请求是新页面访问(一个新的TAB),
if(用户请求URL是Login.jsp&&retUrl==null){

}
lee5593 2007-07-18
flxi78 写道
如果上面的问题解决了,那用户再打开一个tab,并且在地址栏里输入URL地址访问某个特别的页面,怎么办?是显示还是拒绝?如果显示,显示谁的?

一直以来我没有逆向去思考过这个问题,flxi78的疑问应该解释了浏览器为什么不支持多选项卡多用户会话跟踪的原因,如果是这样的话,那我们应该讨论的问题就是怎样防止用户利用不同选项卡进行多用户登陆以规避该设计带来的潜在的风险,各位的看法如何?
flxi78 2007-07-16
另外,楼主说这个应用,如果tomcat关闭cookie就不能正常工作,我是不是能理解成每个request的header中都包含cookie信息?
flxi78 2007-07-16
如果上面的问题解决了,那用户再打开一个tab,并且在地址栏里输入URL地址访问某个特别的页面,怎么办?是显示还是拒绝?如果显示,显示谁的?
Liner 2007-07-15
还有另外一种解决办法:

在当前窗口文档的JavaScript环境中存一个sessionid的副本,并在body的onFocus事件中执行document.cookie="[session_name]=[session_id]"。

这样,不论是选项卡窗口还是新窗口,浏览器Cookie中的sessionid都会被重新设置为当前文档(窗口)的SID。SID恢复了,服务器端会话环境就自然恢复了。

但是这仍然需要修改原始程序。

如果是PHP,可以通过配置session.use_trans_sid为true,让PHP自动在URL中透明地添加SessionID,就不用修改源程序了。
royalics 2007-07-14
大家好,我是个新手,提供一个解决办法,不知道行不行。如有错误,请原谅我的冒失。
1、先在运行环境的后台配置session有效期,确保当用户关闭浏览器时该浏览器注册的session被有效注销
2、在用户的帐号、密码验证通过后,加入一段代码注册一个session,表示该浏览器有用户登录,例如PHP中的代码$_session["login"]="yes";
3、在处理验证用户帐号、密码的页面的最开始处,写一段是否该浏览器有用户登录的验证代码,例如if($_session["login"] == "yes")
如果有,则表示该浏览器有用户登录,提示用户不能进行登录操作
如果没有,则用户可以进入下面的帐号、密码验证流程,并正常登录
注:我只了解PHP,不过我想JAVA和PHP在session上应该是差不多的
rainchen 2007-07-07
有结论了吗
newroc 2007-07-06
jianfeng008cn 写道
newroc 写道
多个tab页使用同一session是合理的,要不然每打开一个tab就要用户重新登陆?你愿意?还是你的用户愿意?
要求不同tab页不同用户,从根上就错了。
这种要求不是不能实现,也没什么难度(反正难度大的方式我是没想到,看了前面的回帖,做法也基本类似),无非就是工作量大点。
楼主比较一下投入产出取舍一下吧。


正常情况是这样打开的tab是同一个session,然后可以登录第二个用户,且tab页间互相不影响,这位同学话说得蛮大,意思理解到位了?

而且携带sessionid的做法,在实际操作中工作应该很小才对,难道各位都直接使用html页面不成。

不知这位同学有没有详细阅读前面的帖子,如果能如你所说,前面的各位的文字就毫无意义了。
ps.请您到网易使用两个用户同时登录看看效果。
jianfeng008cn 2007-07-03
newroc 写道
多个tab页使用同一session是合理的,要不然每打开一个tab就要用户重新登陆?你愿意?还是你的用户愿意?
要求不同tab页不同用户,从根上就错了。
这种要求不是不能实现,也没什么难度(反正难度大的方式我是没想到,看了前面的回帖,做法也基本类似),无非就是工作量大点。
楼主比较一下投入产出取舍一下吧。


正常情况是这样打开的tab是同一个session,然后可以登录第二个用户,且tab页间互相不影响,这位同学话说得蛮大,意思理解到位了?

而且携带sessionid的做法,在实际操作中工作应该很小才对,难道各位都直接使用html页面不成。
angin 2007-07-03
多网页浏览器在标签页中新开的窗口都是共享一个session
如同在ie运行时使用Ctrl+n打开的新窗口一样
newroc 2007-07-01
多个tab页使用同一session是合理的,要不然每打开一个tab就要用户重新登陆?你愿意?还是你的用户愿意?
要求不同tab页不同用户,从根上就错了。
这种要求不是不能实现,也没什么难度(反正难度大的方式我是没想到,看了前面的回帖,做法也基本类似),无非就是工作量大点。
楼主比较一下投入产出取舍一下吧。
myy 2007-06-27
centgo 写道
我也来提供点思路:
2)自己实现一个类似session的功能,不用sessionid,用用户名绑定后台数据,每次访问时传回用户名,根据用户名做不同的操作。


这个也不太好做的。难道要求要求每个URL都要跟“?uid=XXXX”吗?
lee5593
搜索本博客
最近加入圈子
存档
最新评论