這個題目可能有點大了,這里主要討論一種解決safari瀏覽器阻止第三方cookie問題。
場景
公司存在多個域名(a.com,b.com,co.com)這些域名應該統一帳號狀態,a.com為公司主域名,其中帳號系統為passport.a.com,b.com現在做一個活動,需要用戶進行登錄,那么就跳轉到passport.a.com進行登錄,登錄完成完根據參數會跳至活動頁面。由於passport.a.com使用的jsonp的形式對a.com,b.com和c.com就行設置登錄狀態操作(在(
如何創建帳號統一服務)中有詳細說明),其他瀏覽器(chrome、ff、IE等)在默認瀏覽器配置下都沒有問題,只有在safari下存在這個問題,原因在於:safari隱私設置,默認阻止第三方cookie設置,但是只要你訪問過一次(這里的訪問必須是用戶手動操作,不能通過JS進行跳轉操作)它就允許了。如果是這種情況,那么登錄成功跳轉回去,用戶在b.com或c.com仍然沒有登錄狀態?
嘗試解決方案
1.
將頁面放在自己服務器下面
也就是說,將passprot.a.com的登錄頁面在b.com下自己在實現一次,這樣可以保證b.com有登錄狀態,但是存在一下幾點問題:
- 實現成本問題,將登錄這么復雜的邏輯需要自己實現並維護,不利於構建統一的帳號服務體系,增加維護成本
- 只完成了登陸b.com,並不能登錄a.com和c.com,沒有完成帳號狀態的同步
- 如果登錄出現驗證碼而驗證碼又不是b.com提供的服務,同樣會出現cookie無法校驗的問題
2
. 代替用戶訪問一次需要的域名
- 通過前端事件訪問,可以模擬用戶點擊或者直接location跳轉,經過測試發現這種方案不靠譜
- 通過服務端跳轉,b.com訪問一個jump.a.com專門做跳轉處理,可以再到b.com這樣的話就能操作a.com的cookie,但是在登錄場景還是沒有辦法使用,原因可以參考上面的解釋
3.
服務端302跳轉的形式
既然第三方不能操作,那就使用自己的子域就行操作就行了。首先保證自己的東西都放在自己的域名下處理,如果必須要引入第三方的接口時,可以考慮將之前的jsonp請求,轉化為302跳轉的方式實現。這種形式也有問題,safari瀏覽器最大的跳轉次數是15次,超過15次瀏覽器就會無法解析。各瀏覽器302次數限制可以查看
瀏覽器重定向(302)次數限制問題。
確定方案
以上幾種方案,可以根據自己業務的實際情況選擇合適的方式。
針對本文最初提到的場景,我們的解決方案是使用,服務端302跳轉代替jsonp請求的方式完成的。整個實現的流程大致如下:


這樣就完成了所有域名登錄狀態的設置,准確來說是所傳域名列表會被設置上登錄狀態。
總結
這里是以登錄為例,解決safari瀏覽器默認阻止第三方cookie問題的,在其他場景下看情況使用不同的方案,當然在這里也是拋磚引玉,希望能得到更好,更方便的實現方式。再說點兒題外話,討論這個方案用了不少時間,有很多方案很簡單但是我們不能使用是考慮到我們的實現成本問題,已經對用戶的影響,這種情況下,盡可能少的讓用戶來操作什么完成你本身就應該完成的事情。總之一個原則,能不讓用戶做的盡量別讓用戶做,用戶的認知成本和學習成本你都是無法評估的。