關於web端的單點登錄實踐

問題:

假設現在有4個域名,www.a.com,www.b.com,www.c.com,www.d.com,在a.com這個域內登錄了,不種其他3個域名的cookie,如果用戶輸入其他的三個域的時候,也能保證用戶在不輸入用戶名和密碼的時候也能登錄

說在前面的話:

1)在web端登錄和未登錄:使特定的cookie的值生效/失效,這個特定,就是你所制定的規則。

2)問題的關鍵:如何獲得cookie的值,就獲得了帳號的通行證,就可以登錄了,然後就是做你想做的事情了。比如修改,刪除資料,修改密碼,做你想做的任何事情,總之,你控制了這個帳號了。

分析:

1)在www.a.com 這域名下登錄,我們可以將cookie設置在a.com這頂級域名上,如果這個域的子域,比如1.a.com,2.a.com都能取到這個域的cookie的,都能登錄,不存在不能登錄

2)在a.com這個域名下登錄了,如何在b.com,c.com,d.com這個域名下獲得a.com的cookie的值,只要獲得a.com這個域下的該用戶的cookie的值就可以了。

如何取得cookie呢?我們做了以下思考:

1.跨域取cookie,這個是安全的嗎?refer可以偽造嗎,有那些方式?

2.跨域請求是否能獲得header的內容?

3.跨域post提交(iframe+post)是否能獲得iframe裡面的內容?

現在我們看看上面3個問題:

1.跨域,我們這裡思考,採用loadJsonp的形式,這個是安全的嗎,loadjsonp對外都是靜態的,我們可以看,別人也可以看,不同的是我電腦和瀏覽器的狀態,基於這個考慮,我們限制了referrer,即來源,

這個可以擋住一部分,但是這個是可以偽造嗎?查閱了相關資料,前端沒有辦法偽造,但是可以為空,在這個問題上,我們限制了referrer不為空,並且在我們的白名單裡面就可以了。

2.是否能獲得header的內容,我們知道loadJsonp是通過創建script標籤來獲取數據的,因此肯定不能獲得header頭信息的,ajax是可以的,只要設置type: "HEAD", 就可以獲得頭信息,但是ajax是不能跨域的,

因為我們排除了跨域獲得header的可能性

3.由於安全沙箱的限制,iframe裡面如果不是本域的內容,肯定不能獲取得到。

基於以上考慮,我們就採取了loadjsonp+限制referrer的形式來跨域獲得cookie,獲取cookie後,我們就往本域的根目錄寫入,然後就可以在本域內實現登錄。而不涉及到其他域的cookie問題。

方案實施:

方案1:提供通用js, 通過設置基準域名cookie(例如www.a.com), 其它業務均從基準域名獲取cookie的方式,來獲取登錄狀態。

登錄時設置兩個基準域和當前域下的cookie,其它業務需要時再拉取基準域名cookie來設置自身cookie。

此方案存在的問題:

需要載入js,只能在頁面載入完js到瀏覽器後才能執行,設置本域cookie, 需要再次刷新頁面才能是登錄狀態。

業務方的頁面有二種情況不能用這種方案:

1.登錄後才能訪問,一般會在後端判斷用戶是否未登錄,然後直接跳轉到登錄頁面,

2. 不登錄也能訪問,可是是否登錄決定頁面的部分顯示數據(通用js自動登錄後刷新本頁面可以得到效果,但是用戶體驗差)。

此方案比較適合頁面無需登錄也能訪問,並且登錄後頁面效果沒有變化的頁面,靜態頁面比較適合這種情況。

由於要檢測當前域是否是登錄狀態,然後要請求基準域,並且設置本域cookie,對基準域本身的服務壓力大,幾乎是業務方的所有pv*n

方案2: 提供通用登錄js, 每次需要用戶輸入用戶名,密碼之前,先去基準域名獲取登錄狀態,如果是已經登錄,就顯示:已檢測到已登錄用戶:XXX, 點擊直接登錄或者換其他賬號登錄,

此方案存在的問題:

不是通常意義的單點登錄,只是縮短了用戶登錄的流程,減少代價

優點:

不用業務方每個頁面都部署,對業務方完全透明;

對基準域的請求壓力不大;

就算在目前輪詢的事情下,也存在單域cookie失效導致用戶未登錄的情況,通過這種方式也能改善用戶體驗;

安全風險:

目前所有域下都是用的同一個cookie, 任何一個也沒如果出現xss漏洞,都會導致用戶cookie泄露,安全完全不可控, 單點登錄會擴散這種風險。

參考文章:http://developer.51cto.com/art/201104/255729.htm

歡迎大家拍磚。謝謝!!


推薦閱讀:

SSO單點登錄的發展由來以及實現原理
Salesforce中的單點登錄簡介

TAG:實踐 | 登錄 | 單點登錄 | 關於 |