前段時間在項目里遇到了一個比較頭疼的問題,就是高版本的Safari中默認會阻止第三方cookie,這使得使用Safari瀏覽器的用戶無法按照正常的業務邏輯進行操作。
問題展現
知識點
什么是第三方cookie呢?在訪問一個網站A時,網站A算作第一方,如果網站A中引用了另一個網站B(網站B的域名與網站A的域名不同)的資源,這時這個網站B就被認為是第三方。需要注意的是,這兒區分不同網站的標准是域名是否相同,而不是這兩個網站是否由同一個公司運營。比如,taobao.com和tmall.com被認為是兩個網站,盡管它們都屬於阿里集團。
問題demo
僅供參考,新建兩個basic MVC項目CookieSolution和TestCookieSolution。假設CookieSolution里面是正常的業務邏輯,有兩個頁面Page1 和Page2 ,相應代碼如下:
public ActionResult Page1() { Session["mySession"] = "Jackbase"; return View(); } public ActionResult Page2() { if (Session["mySession"] != "Jackbase") { return Redirect("Page1"); } return View(); }
后台代碼如上,前台代碼如下:
@*Page1的前台代碼*@ <h2>Page 1</h2> <a href="/Home/Page2">Go to Page 2</a> @*Page2的前台代碼*@ <h2>Page 2</h2> <a href="/Home/Page1">Back to Page 1</a>
可以看出在Page1的初始化里設置Session["mySession"]的值,在Page2的初始化里檢測Session["mySession"]的值,如果值不對,則跳回Page1。在TestCookieSolution中的頁面里用iframe引用CookieSolution的頁面,前台代碼如下:
<h2>Test</h2> <iframe src="http://www.cookieSolution.com"></iframe>
后台
public ActionResult Test() { return View(); }
不要問我www.cookieSolution.com是什么,自行在hosts里添加。
127.0.0.1 www.cookieSolution.com
一切准備就緒,在IIS里面新建兩個站點,分別綁定CookieSolution(80端口)和TestCookieSolution(8050端口)
訪問http://localhost:8050進行測試(基於Safari瀏覽器),發現點擊Go to Page2完全不能跳到Page2中,依然在Page1 中。Safari安全機制阻止了第三方的Cookie以及Session,網上有很多方法我都做了一一嘗試,什么P3P幾乎完全不行...
解決方案
既然瀏覽器阻止的是第三方Cookie及數據,那么我們就想辦法讓瀏覽器認為iframe中的頁面不屬於第三方不就行了嗎?那么我們在進入Test頁面之前先打開www.cookieSolution.com中的一個頁面,設置cookie,然后再跳轉到Test頁面,這時www.cookieSolution.com就不在屬於第三方了。
在TestCookieSolution新增一個頁面,PreTest.
public ActionResult PreTest() { return View(); }
<h2>PreTest</h2> <a href="http://www.cookieSolution.com/Home/CookieMaker?url=http://localhost:8050/Home/Test">Go to Test</a>
在CookieSolution的HomeController里面新增方法
public ActionResult CookieMaker() { // 隨意設置一個Session Session["Prepare"] = "jb"; return Redirect(Request.QueryString["url"]); }
這樣就解決了這個難題了,有興趣的同學可自行測試,這里就不過多演示了。
參考資料
Missing cookies on iframe in safari 5.1.5
Safari 3rd party cookie iframe trick no longer working?
Ipad Safari iframe cookie 當瀏覽器默認禁用第三方COOKIE
本文所用代碼demo