多域名(跨域)登录信息共享解决方案乱弹
现有需求如下: login.nx.com 是 nx.com 的二级域名, login.nx.com 是 nx.com 的登录中心应用,现在有两个拍马屁的网站 (Sb.com 、 Sx.com) 想跟 nx.com 共享登录,分享一下 nx.com 的用户资源,现在的整合登录的目标是 : 任何一家网站登录后,到其他网站后都不需要再重新登录,姑且叫做良民通行证吧, (souhu 人家也是这么叫的 )
我们都知道,要共享登录,一般情况下是需要共享应用 session 中的信息的,而 session 存储一般都是只在单台服务器的内存中的,其他服务器上的应用需要共享只有通过复制的方式,这是效率低下的,可以进行 session 改造 , 这里不具体讨论这个问题,可以参考《SNA session剖析》 。通过上面一篇文章我们知道,登录相关信息可以存储在服务端,也可以存储在客户端,要和其他站点共享这些信息,就需要解决如何在所有站点下同步这些信息的问题,而解决同步的关键又在要解决跨域问题,以服务端存储为例:
客户端 cookie 中只有 sessionId ,登录相关信息全部在服务端,通过 sessionId 在服务端即可获取登录信息,可以这么理解,只要 sb.com 、 sx.com 、 nx.com 具有相同的 sessionId ,那么在服务端他们就可以根据相同 sessionId 拿到登录状态,也就共享了登录信息,基于这个思路,解决方案有如下两个,各有优缺点:
1、 浏览器访问任何一个未登录网站都跳转到 login.nx.com 登录中心进行登录,登录成功后设置登录状态,并设置 cookie 保存 sessionId ,其中 domain=.nx.com, 此时 ,nx.com 包括其子域名都能成功获取到 sessionid ,同时返回给客户端其他需要共享登录的域名列表,假设如下 ( 这里除了使用 script ,其实 ajax 相关的技术都可以 , 例如 iframe 、 img, XHR, 另外注意下 P3P 的问题 ) :
<script src=”http://sx.com/pass?sessionid=123456”></script>
<script src=”http://sb.com/pass?sessionid=123456”></script>
这里访问 /pass 目的只有一个,就是将 sessioinid 给相应的域名,然后 /pass 接收到 sessionId 后写入到自己域名下 cookie 中,这样 sx.com 、 sb.com 域名下都有了这个 sessionid ,好, cookie 设置大功告成,然后该页面再 redirect 到其他应该去的页面。只要在这几个域名下,就不需要再重新登录。
优点 :登录处统一设置登录相关 cookie ,集中管理, 除了第一次登录以外其他时候个系统各自为政,登入时统一重新创建 sessionId ,登出时如果 session 存储在服务端,则直接清除服务端即可,如果存储在客户端,则跟登录时一样,分别请求登出即可。
缺点 :但是登录时间会有点长,如果支持域名太多,这个估计有点郁闷了,不过支持过 4-5 个域名问题不大,如果 session 存储在客户端,则登出时间也可能会稍长。
2、 浏览器访问任何一个未登录网站(例如 sx.com )都跳转到 login.nx.com 登录中心进行登录,登录成功后设置登录状态,并设置 cookie 保存 sessionId ,其中 domain=.nx.com, 此时 ,nx.com 包括其子域名都能成功获取到 sessionid ,然后带着 sessionId 参数跳转到 http://sx.com/pass?sessionid=123456&redirect_url=sx.com/xx.htm , sx.com/pass 分析出 sessionId 后进行存储,然后跳转到 sx.com/xx.htm 目标页,此时这个页面是登录状态的。此时如果访问 http://sb.com/yy.htm 时, sb.com 会先检查是否存在 sessionid, 如果不存在,则 302 跳转请求 login.nx.com/pass?domain=sb.com&redirct_url=http://sb.com/yy.htm ,由于之前 login.nx.com 已经登录,此时的请求会将该域名下的 cookie 中 sessionId 带到服务器, login.nx.com 获取到 sessionId 后,组装成 http://sb.com/pass?sessionid=123456&redirect_url=http://sb.com/yy.htm,这个过程,与 sx.com 处理过程一致,如此就完成了登录,如果存在 sessionId 则不需要去登录中心拿 sessionid 了。
优点 :登录时间完全缩短,不论多少个应用都不会影响登录。
缺点 :未登录也需要创建 sessionId, 因为如果没有 sessionid ,则每个需要登录信息的页面 ( 那种登录与否都可以看的页面 ) 都要去 login.nx.com 去访问一次,这样再 nx 的也受不了这样折腾啊, 另外,由于未登录时 sessionId 已经生成,所以用户登录后这里会重复利用 sessionid ,除非浏览器关闭。另外登出时由于要清除所有域名下的 sessionId ,可能速度会有点慢,当然也可以不清除,那么在浏览器关闭之前,这个 sessionId 会被重复利用,可能稍微有点安全隐患。
注:网上流传着一种在两个域名下共享 cookie 的方案,即 a.com , b.com 如果需要共享 cookie ,则在访问 a.com 将 cookie 设置成 cookie.setDomain(‘.b.com’) ,这样 b.com 就可以访问这个 cookie , a.com 由于是生成这个 cookie 的应用,因此也可以访问,这就完成了共享,其实这是错误的,在 a.com 的域名下完全不可能存取一个 domain=.b.com 的 cookie ,既然不能基本的存储都不可能,何来共享?各位不服气的看官可以自己回去服务端或者 js 设置一下,看设置成 domain=.126.com 后的 cookie 是否保存下来了,,然后再回来批判我,我自会删除这段东东。