多站點整合—單點登錄簡單方案

問題描述:在一個比較複雜的網站環境下。有多個產品向外提供服務。每個產品下都有自己的用戶登錄界面。現在需要設計一個統一的登錄界面。當用戶在這個界面登錄後就可以自由的使用各個產品和服務。同時意味着用戶用一個帳號可以在不同服務裏登錄,另一方面就是在一個服務裏面登錄後可以無障礙的漫遊到其他服務裏面去。

實際應用:Sohu的Passport將focus.cn,17173.com,sogou.com,chinaren.com這四個域名下的產品全部整合在一起了。用戶在這四個站點中任何一個地方都可以登錄。當用戶登錄後可以自由的使用其他域名下的服務。現在很多網站上都有bbs blog album服務。這些服務一般也是自己維護自己的用戶信息。當發展到一定時候,也需要一個Passport機制整合所有服務,使用戶可以單點登錄。

Sohu的實現方案
http://passport.sohu.com/ 登錄後 fiddler可以攔截到如下的返回信息:

看原大圖


由於passport.sohu.com的登錄界面使用了iframe隱藏提交。所以頁面沒有看到刷新。隱藏的iframe把用戶名和加密的password和其他信息發送給了passport.sohu.com。passport.sohu.com在Response中設置了成功登錄的cookie。這個cookie可以證實這個用戶成功登錄了passport.sohu.com。

看原大圖


當用戶在Passport成功登錄後。客戶端的Javascript根據成功登錄的標誌,操作iframe請求http://passport.sohu.com/sso/crossdomain_all.jsp?action=login 因爲在同一個域名下,沒有跨域,在這次請求中,上次成功登陸的cookie會被一併帶着回去。服務器端檢查到成功登錄的cookie後會Render回一段同時登錄多個站點的html。

看原大圖


這段html 要向4個地址發送請求。截至到現在都是在相同的Domain(passport.sohu.com)請求和返回,爲真正的跨站點登錄做準備,真正的跨站點登錄還沒有開始。下面passport.sohu.com通過sso/crossdomain.jsp 在服務器端進行Redirect 設置http head 爲302進行跳轉。跳轉後在這個跳轉後的域名下設置登錄成功的cookie。這就是sohu實現跨站點登錄的核心過程。下面是passport.sohu.com登錄17173.com的過程。
1. 通過http://passport.sohu.com/sso/crossdomain_all.jsp?action=login Render回來的script <script type="text/javascript" src="http://passport.sohu.com/sso/crossdomain.jsp?action=login&domain=17173.com"></script> 請求同域下的http://passport.sohu.com/sso/crossdomain.jsp?action=login&domain=17173.com 這時passport.sohu.com下成功登錄的cookie會被帶回去。

看原大圖


2. 服務器看到成功登錄的Cookie後。在服務器端計算出一個加密後的17173.com的登錄Url,並Redirect到這個Url。

看原大圖


3. 17173.com從url的QueryString中取得信息。並在Response中設置Cookie。這個Cookie終於寫到了17173.com下。而不是passport.sohu.com下。從而使得用戶在17173.com下登錄。其實用戶在17173.com下手動登錄也是寫上同樣的Cookie。以後用戶再訪問17173.com的頁面時這個Cookie會被帶回去。這就表示用戶在17173.com下成功登錄過了。

看原大圖


經過上面的步驟。用戶在passport.sohu.com下登錄的同時也在其他站點登錄了。

在上面的過程中,最核心的技巧就是在指定的域下寫入想要的Cookie:

1. Sohu使用了在同一個域名登錄後通過再次請求這個域名下某個鏈接後,得到要登錄站點的請求Url,通過javascript使隱藏的iframe請求要登錄站點的Url,服務器端接到請求Redirect到要登錄站點,然後通過Response寫入Cookie,完成跨域名寫Cookie的操作。這種寫Cookie的方式,需要在跳轉時對請求的QueryString進行加密。接受方需要對QueryString進行解密。

2. 這種做法在服務器端不需要特別的處理。只要寫好相應Post操作 WriteCookie操作 Redirect操作 就可以了。在FireFox下就可以正常工作了。但是在IE下寫Cookie的操作還不行,總是寫不進去Cookie。需要在Response中加入一段特別的Header. P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"

這個Http Header 是P3P安全的要求。P3P的詳解 http://www.oreilly.com.cn/book.php?bn=7-302-07170-5
微軟對這個的解釋:http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q323752

一個更加輕量級的方案

Sohu的通行證方案已經可以輕鬆的將各個域名下的用戶都同步登錄了。但是在實現上Sohu會讓客戶端的瀏覽器請求兩次passport.sohu.com。在第二次得到一個登錄多個站點的地址列表。在第三次請求時通過本域下的cookie進行身份驗證,最後在服務器端跳轉到一個含有加密Key的其它域名的Url地址,最終寫入登錄成功的Cookie。除去最開始的登錄,要求用戶在登錄後再進行兩次請求。並且服務器端要再做一次跳轉。Sohu的做法可能由於Sohu服務器環境和數據存儲的結構所決定。

其實總共只需一次登錄請求,和每個域名下一次請求就可以完成多站點登錄了,同時也不需要服務器端的跳轉。

看原大圖


跨站點的請求由script的src發出。各個域名下的ssologin處理QueryString中的key,解密key,驗證Key的合法性。在Response中寫入登錄成功的Cookie。完成跨站點Cookie的寫入。

兩種方案的比較

1. Sohu使用的登錄方式,請求次數多,但是每次請求都有對應的驗證過程,在服務端跳轉時,重要的跳轉Url地址在HttpHeader中,使得跳轉地址更加安全,使得用戶在跨域登錄時非常安全可靠。

2. 輕量級方案的登錄方式,請求次數少,沒有服務器端的跳轉,對服務器壓力小。但是需要對Key進行加密解密。跳轉的Url會在Response的Http Body中Render給用戶。在使用輕量級方案的時候,最好在Key中加上時間戳,過期時間設置爲3分鐘。Key過期認爲這個Key是非法Key,不在Response中寫入登錄成功的Cookie。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章