论坛首页 Java企业应用论坛

跨域访问时Session丢失

浏览 72939 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-11-07   最后修改:2008-11-07
我目前在做一个电子购物网站。这个网站对应着不同的国家,将会有不同的域名。比如,对英国会是www.xxx.com.uk,对中国可能是www.xxx.com.cn。但是,在涉及到支付时,都会转向一个地址:https://checkout.xxx.com。这些不同的域名,实际上是指向同一台服务器的同一个Server。

在实际使用中,由于域名不同,但又需要跨域访问。主要应用场景是,客户在英国的购物网站-http://www.xxx.com.uk(简称:uk站) 中往购物车中放置了商品,最后,转至https://checkout.xxx.cml来进行支付工作。这时就碰到了跨域访问时,Session丢失的问题。

先说一下,我们用的服务器是Tomcat。Tomcat是通过url中的jsessionid以及cookie中的jsessionid来取得会话ID的。Tomcat先会查询URL后面有没有跟jsessionid。然后,再去解析Cookie中的jsessionid。如果cookie中有的话,那么,不管之前从URL中有没有找会jsessionid,都会使用cookie中找到的。详情参见Tomcat中的CoyoteAdapter类。


问题1:我打开浏览器,在uk站中买了一件商品,当我点击页面中的Check Out链接时,页面跳入了https://checkout.xxx.com的支付页面后,用户购物车里的商品在跳转在支付页面中消失了。

问题原因:由于两者的域名不同,在跳转到支付页面时,丢失了原来的会话信息。无论是URL还是cookie中都找不到会话ID了。Tomcat创建了一个空空如也的新会话。

解决办法:重写链接,在支付链接后加上jsessionid,也就是像这样https://checkout.xxx.com;jsessionid=A8AB5D19484BFCF26E8E4F708E2F6C91.jvm1。在转到支付页面时,由于此时浏览器中https://checkout.xxx.com域名的cookie中没有任何信息,则Tomcat会使用URL中取得的sessionId。这样,就能继续使用uk站中的会话了。


问题2:通过URL重写,我们可以在https://checkout.xxx.com的页面能够看到购物网站的信息了,我本以为一切到此结束了,没想到,又出现了新的问题。在支付过程中,页面使用Ajax和服务器做些数据的交互。可每次交换,服务器居然都报session中找不到用户登录信息的exception。仔细看了下日志,服务器在处理支付页面上的初次的Ajax请求时,居然创建了一个新的Session。

问题原因:在通过Ajax发送请求时,Tomcat无法从URL中取得会话ID,之后,便试着去Cookie中查询信息。可此时,https://checkout.xxx.com下的cookie竟然是空空如也的。之前从购物网站跳转至https://checkout.xxx.com时,Tomcat从URL中取得了原会话ID。此时,Tomcat是继续使用原有session,而没有创建新的session,便没有向浏览器的cookie写入信息JSESSIONID的信息了(这是我猜测的,没看代码证实过)。

解决办法:既然能在转入支付页面时使用原有的Session,那么,就在刚转入支付页面时,把sessionid写入cookie不就行了吗?这里我暂时用js把sessionid写入了cookie中。之后做了几次测试都顺利地通过了。


问题3:好了,当我以为一切都OK的时候,又出现了一个问题。我先打开www.xxx.com,也就是checkout.xxx.com的主域名。接着再打开www.xxx.com.uk进行购买的操作。此时,当我转入https://checkout.xxx.com时,session又丢失了。

问题原因:其实,这里的session没有丢失。通过SessionID来看,在转入https://checkout.xxx.com时,由于之前打开了其主域名www.xxx.com,在cookie中留下了host为xxx的session的信息。而在从购物网站转入支付页面时,Tomcat先从URL中取得了uk站的会话ID,但是最后又从cookie中取到了www.xxx.com的会话ID,并且使用了它。

解决办法:暂无。

候选办法1:修改Tomcat中的CoyoteAdapter类,让它以URL中的jsessionid为主,以cookie中的为辅。但是,这样做就会有个很大的问题。那就是,如果用户收藏了一个购物站中的一商品的链接。而这个链接后面又跟了一个已经失效的jsessionid,那么,服务器端会由于拿不到这个失效的jsessionid对应的Session,而去创建一个新的会话。这样子,就很有可能在同一个浏览器中访问相同的站点,但却面对着不同的会话。

候选办法2:让公司再单独开个域名,专门负责处理check out。在进入这个域名前,对header中的referer信息进行验证,如果来自购物网站,则对请求进行正常处理。反之,则重定向到其它的域名。不知道重写向时,会不会向cookie中写入信息?这个不知道可行否。

不知道各位对应问题3的情况有什么处理建议吗?还望大家不吝赐一二呀。

PS. 据说,SSL证书是针对域名收钱的。所以,我们针对不同国家或有不同的域名。但对于支付,都是跳转到https://checkout.xxx.com这一个来进行的。这样,只需要一张SSL证书就行了。

补充:目前我们都只是在做一个国家的站点,checkout测试也是针对一个国家的。但实际上,各个不同的国家的站点,其实是不同的webapp。它们在支付时都会转向的那个checkout网站,也只能是个独立的webapp了。那么,这就不是单靠个sessionid就能和各个国家的站点共享他们的session的问题了。 而是两个不同的应用间,共享数据的问题了。

兜了圈子,猛然发现,现在我在努力解决的问题,不是将来要实际面对的问题。狂汗。

   发表时间:2008-11-07   最后修改:2008-11-07
购物车里的商品不持久化的吗?
考虑一个情节:
比如,我在UK买了一包烟,突然我干其他事情去了。。。。

两天后我又登陆,这时候如果我查看我的购物车的话,我上次买的烟(未付账)应该还在车里才对

所以我觉得应该把购物车里的货物持久化。。。
然后付账的时候只要用户的ID就可以了嘛,再根据用户ID从数据库里读货物,如何?
1 请登录后投票
   发表时间:2008-11-07  
你写的真详细,我也认真的看完了,提出2点。

www.xxx.com.uk和www.xxx.com.cn属于不同的域,所以不能共享cookie,
但我不知道他们是否可以同时共享www.xxx.com的cookie。

保存cookie的时候,把所有可能的域都进行保存。
0 请登录后投票
   发表时间:2008-11-07   最后修改:2008-11-07
taupo 写道
购物车里的商品不持久化的吗?
考虑一个情节:
比如,我在UK买了一包烟,突然我干其他事情去了。。。。

两天后我又登陆,这时候如果我查看我的购物车的话,我上次买的烟(未付账)应该还在车里才对

所以我觉得应该把购物车里的货物持久化。。。


谢谢LS这个兄弟的回复,看了你的回复,我突然又想到一个严重的问题。

目前我们都只是在做一个国家的站点,checkout测试也是针对一个国家的。但实际上,各个不同的国家的站点,其实是不同的webapp。它们在支付时都会转向的那个checkout网站,也只能是个独立的webapp了。那么,这就不是单靠个sessionid就能和各个国家的站点共享他们的session的问题了。

那么,可能就只能持久化出去,然后各个webapp间,通过某种方式进行沟通,进行协作处理了。

引用
然后付账的时候只要用户的ID就可以了嘛,再根据用户ID从数据库里读货物,如何?

这句话,给了我很大的启发,谢谢 :-)
0 请登录后投票
   发表时间:2008-11-07  
可以考虑单点登录方案,或是商业服务器。
tomcat应该是不支持session跨域的。
0 请登录后投票
   发表时间:2008-11-07  
jeff.chuh 写道
你写的真详细,我也认真的看完了,提出2点。

www.xxx.com.uk和www.xxx.com.cn属于不同的域,所以不能共享cookie,
但我不知道他们是否可以同时共享www.xxx.com的cookie。

保存cookie的时候,把所有可能的域都进行保存。


谢谢你认真的看完 :-), 我的语言表达能力非常有待加强,有的地方太不够简洁了。
我试过了,www.xxx.com.uk无法共享www.xxx.com的cookie的。它们都是不同的域名。
0 请登录后投票
   发表时间:2008-11-07  
推荐TerraCotta
0 请登录后投票
   发表时间:2008-11-07  
存数据库里,大家共用一份数据库购物车。
1 请登录后投票
   发表时间:2008-11-07  
假设你的那个checkout.xxx.com是支付宝或网银,你会怎么办
方案显而易见——把支付请求加密后跟在url后面传给checkout.xxx.com
1 请登录后投票
   发表时间:2008-11-08  
你用session保存所购商品的方式,也是一般人所用的方式。为了共享session, 你把URL重写带上jsessionid. 但是有一个问题,就是你要把uk应用和checkout应用都必须布置在一个Tomcat上。如果用户数量很大的话,可能需要把这些应用都分成不同机器来布置,你的这个方法就不好使了。

商品是保存在cookie里(当然这里有一个跨域访问cookie问题,要解决好),还是持久化(好像大多数购物类网站都没有持久化)呢? 估计还得根据需求来确定。如果持久化的话,有个哥们说三两之后来看,我之前买的烟还在。那如果是三两年之后呢。 这些商品是不是还要保留呢?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics