關於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
歡迎大家拍磚。謝謝!!
推薦閱讀: