跨域(cross-domain)訪問 cookie (讀取和設置)

Passport 一方面意味着用一個賬號能夠在不一樣服務裏登陸,另外一方面就是在一個服務裏面登陸後能夠無障礙的漫遊到其餘服務裏面去。坦白說,目前 sohu passport 在這一點實現的很爛(不過俺的工做就是要把它作好啦,hehe)javascript

搜狐的 SSO 需求比較麻煩,由於它旗下有好多域名:sohu.com、chinaren.com、sogou.com、focus.cn、17173.com、go2map.com,登陸用戶漫遊的主要障礙也來自於此。php

之前億郵的郵件系統在和別的系統整合的時候是提供一個 URL,用戶從第三方系統裏面點擊這個連接就能夠生成訪問郵件界面所需的 cookie,而後進入郵件。這個方式的確頗有效,但問題是:
1. 每一個外部連接都必須用特殊的 URL 跳轉,維護很麻煩
2. 兩個系統集成已經很麻煩了,如果集成的系統有好幾個,彼此都須要跳轉而缺少一箇中心機制就成了噩夢
3. 根本沒法處理用戶直接在地址欄輸入地址進行訪問的狀況html

即便是跨域,上述的解決方法相對來講仍是容易的。
A. 首先是全部登陸必須首先經過一箇中央服務器進行認證,而後在它那裏給瀏覽器種下 cookie(下面稱之爲 sso cookie)
B. 當用戶訪問另外的域名 app 的時候,瀏覽器是沒法直接發送 sso cookie 給服務器認證的。此時應該利用 javascript,動態建立一個隱藏的 iframe,讓其訪問 sso
C. 這個 iframe 的請求是能夠把 sso cookie 送給 sso server 的。sso server 驗證 cookie 後,返回一個重定向頁面到 app 的某個 URL,由該 URL 設置 app cookie
D. 此時瀏覽器上可看見的頁面容器實際上也是能夠和重定向回來的內容交互的。好比能夠用 js 控制發現重定向頁面成功返回後,就刷新整個頁面,讓它看起來和用戶登陸後訪問沒有什麼區別。java

下面是真正的技巧:怎樣才能在 IE 裏面跨域去設置 cookie
上述技術看起來是否是很好?但它的前提是全部的登陸都 post 到 sso server 上,認證成功後再返回 app 頁面。可我接受到的需求之一就是要支持頁面無刷新登陸。node

哈!就是說原本在 chinaren.com 上提交登陸表單的 action 應該是 passport.sohu.com 這個 sso server。但是在 AJAX 大潮下,chinaren 計劃採用 XMLHTTPRequest 提交,這個就麻煩了,由於是不能跨域來提交的。跨域

那麼解決方法就是跨域產生 cookie,即 js 發現口令校驗成功後,再在 passport.sohu.com 上種上合法的 cookie.瀏覽器

套用上面的跨域讀 cookie 的方案彷佛很簡單去推論:就是建立一個隱含的 iframe,讓那個 iframe 去調用 passport.sohu.com 的 URL 來產生 cookie。很遺憾,此方法在 Fx 下工做的很好,可是不能在 IE 上應用。(在 IE 狀態欄上顯示 cookie 隱私警告,紅色圓底白橫槓)服務器

我試了不少不少方法,包括建立 、 node,包括用 js 設置,但都一次次被 IE 無情的擋在了瀏覽器外。google 之,也沒有任何真正可用的答案,中文網頁要麼介紹的方法是錯的,要麼說無解。cookie

最後仍是在 chinaren 一哥們的幫助下,翻出了他們所使用的,以和 alumni.sohu.com 交互的方法(不知道是哪位牛人發現的),只須要設置 P3P HTTP Header,在隱含 iframe 裏面跨域設置 cookie 就能夠成功。他們所用的內容是:app

P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"

最後是我作的一個小小的演示:cookie 怎麼在 vmx.cn 和 dup2.net 之間交互

1. http://qiuyingbo.test.vmx.cn/cookie.php

2. 隨便輸入什麼,點 reset cookie,就能夠看到 vmx.cn 的 cookie 已經被設上了

3. 在該頁面點鏈接到 http://www.dup2.net/vmx/cookie.html

4. 點"get corss-domain cookie" .. (此時 js 會去建立一個iframe,請求 qiuyingbo.test.vmx.cn ,返回頁面把 cookie 值做爲 GET 參數重定向回 dup2.net 的另一個URL。)

5. 點 "display corss-domain cookie" .. 就能夠看到 vmx.cn 的 cookie 了

6. 在該頁面的輸入框中輸入其它的值,而後點 "set cross-domain cookie",該行爲將主動設置 vmx.cn 的 cookie

7. 點連接回到 http://qiuyingbo.test.vmx.cn/cookie.php ,就能夠看到新的值了

網上看了別人介紹的一片文章,說使用P3P能夠完成跨域COOKIE操做,感受很COOL,不過沒有提供源代碼,我胡亂寫了一下,你們看看。

實際工做中,相似這樣的要求不少,好比說,咱們有兩個域名,咱們想實如今一個域名登陸後,能自動完成另外一個域名的登陸,也就是PASSPORT的功能。

我只寫一個大概,爲了測試的方便,先編輯hosts文件,加入測試域名(C:\WINDOWS\system32\drivers\etc\hosts)

127.0.0.1       www.a.com
127.0.0.1       www.b.com

首先:建立 a_setcookie.php 文件,內容以下:

<?php 
//header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); 

setcookie("test"
$_GET['id'], time()+3600"/"".a.com"
); 
?>

而後:建立 a_getcookie.php 文件,內容以下:

<?php 
var_dump
($_COOKIE
); 
?>
 

最後:建立 b_setcookie.php 文件,內容以下:

<script src="http://www.a.com/a_setcookie.php?id=www.b.com"></script>

----------------------------

三個文件建立完畢後,咱們經過瀏覽器依次訪問:

http://www.b.com/b_setcookie.php
http://www.a.com/a_getcookie.php

咱們會發現,在訪問b.com域的時候,咱們並無在a.com域設置上cookie值。

而後咱們修改一下a_setcookie.php文件,去掉註釋符號,a_setcookie.php即爲:

<?php  
header
('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'
);  

setcookie("test"$_GET['id'], time()+3600"/"".a.com"
);  
?> 

再次經過瀏覽器依次訪問:

http://www.b.com/b_setcookie.php
http://www.a.com/a_getcookie.php

此次,你會發如今訪問b.com域的時候,咱們設置了a.com域的cookie值。

末了補充一句,彷佛只有IE對跨域訪問COOKIE限制比較嚴格,上述代碼在FIREFOX下測試,即便不發送P3P頭信息,也能成功。不過IE是老大啊。

相關文章
相關標籤/搜索