不同系统间的账户登录-Cookie跨域
这两天在做:让两个系统间的帐号同步,其中涉及到跨域登录.
背景是这样的:现在有两个系统SystemA和SystemB,要求在SystemA里可以注册SystemB的帐号,同时注册SystemB的时候需要依赖一个新的SystemA的帐号,并且要求在登录SystemB的时候同时登录SystemA的新帐号,并且在同一个浏览器内可以同时登录SystemA的初始帐号SA,SystemB的帐号SB和SystemA的新帐号SAN.
系统SystemA和SystemB都是采用Cookie记录登录操作的. 因此需要同时有SA, SB, SAN三者的Cookie.
解决方案是:使用三个域名(abc.com
, sb.abc.com
, newsa.abc.com
),其中SA访问abc.com
进行登录, SAN访问newsa.abc.com
进行登录, SB访问sb.abc.com
进行登录. 其中abc.com
和newsa.abc.com
都指向SystemA, sb.abc.com
指向SystemB. 这样SA登录的时候使用域abc.com
的Cookie, SAN登录的时候使用newsa.abc.com
的Cookie, SB登录的时候使用sb.abc.com
的Cookie.
- 跨域登录:其实很简单,首先使用SA登录
abc.com
,这时候已经种植了abc.com
的Cookie, 然后用SB登录SystemB成功后种植了sb.abc.com
的Cookie, 登录SystemB的时候动态生成一个script,该script的src指向newsa.abc.com
的一个URL,该URL负责种植域newsa.abc.com
下的Cookie(也就是采用动态载入异域的script解决跨域).
在sb.abc.com
的登录页面ajax验证登录成功后执行下面的代码,动态引入newsa.abc.com
的一个URL作为dom-script.
你可能会问为什么不在
sb.abc.com
直接种植newsa.abc.com
下的Cookie呢?
因为种不了,这属于跨域了. sb.abc.com可以种植sb.abc.com和abc.com下的Cookie, 无法在同级别的二级域名下种植Cookie.
1 | function loadScript(url, callback, callbackData){ |
嗯,还支持简单的回调 ~
- 父域和子域Cookie的发送优先级
没错,通过上面的异步引入newsa.abc.com
一个种植Cookie的URL我们可以成功种植Cookie.
But, 当我们访问newsa.abc.com
的时候发现浏览器在Header里发送的不是 newsa.abc.com
的Cookie, 而是abc.com
的Cookie. 即当父域和子域的Cookie同时存在时访问子域的URL,浏览器会优先发送父域的Cookie.
我们翻阅下种植Cookie的方法:
1 | bool setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] ) |
path
就是我们解决问题的关键,由于项目正好不是在域名下的'/'根目录
,所以对于子域的Cookie, 我们种植到项目目录下,父域的Cookie还是种植到'/'根目录
, 假设项目目录为:/project
,当访问abc.com/project
下的URI时,发送的是abc.com
的Cookie, 访问newsa.abc.com/project
的URI时,发送的是newsa.abc.com
的Cookie(因为我们设置了newsa.abc.com的Cookie的path,所以优先发送. )
当然我们完全可以将newsa.abc.com
替换成def.com
,这样就不涉及子域,父域的Cookie共享问题了,但是我们有自己的业务考虑,使用newsa.abc.com
对用户来说更能体现我们业务的紧密型.
总结下Cookie的跨域共享:
- 在可读取的path下子域可以共享父域的Cookie,同时如果二者都存在,优先使用匹配当前path的Cookie.
- 不同的子域之间不能种植Cookie.
- 子域可以种植父域的Cookie.
- 父域不可以种植子域的Cookie.
- 父域不可以共享子域的Cookie.