總結:
同源ajax請求是可以自動攜帶cookie的
而非同源需要客戶端和服務端都做處理:
1.客戶端需要對xhr對象設置withCredentials:true
2.服務端需要設置響應頭 access-control-allow-credentials:true
同時必須指明 access-control-allow-origin 為服務方的origin, 不能為*
======================================
之前都有這樣一個理解:
ajax請求時是不會自動帶上cookie的,要是想讓他帶上的話,必須喲啊設置withCredential為true。
這個說法會讓人產生完全扭曲的誤解,我就是其中之一。
完整的無歧義的表述應該是這樣:
1.ajax會自動帶上同源的cookie,不會帶上不同源的cookie
2. 可以通過前端設置withCredentials為true, 后端設置Header的方式讓ajax自動帶上不同源的cookie,但是這個屬性對同源請求沒有任何影響。會被自動忽略。
3. 這是MDN對withCredentials的解釋: MDN-withCredentials ,我接着解釋一下同源。
眾所周知,ajax請求是有同源策略的,雖然可以應用CORS等手段來實現跨域,但是這並不是說這樣就是“同源”了。ajax在請求時就會因為這個同源的問題而決定是否帶上cookie,這樣解釋應該沒有問題了吧,還不知道同源策略的,應該去谷歌一下看看。
實驗
第一步: 建立一個本地服務器
1.新建一個demo文件夾,進入文件夾,用php -S localhost:9000開啟一個本地服務器
2.在demo文件夾下新建一個index.php文件, 內容為:
-
-
header( "Access-Control-Allow-Origin: http://localhost:9999");
-
header( 'Access-Control-Allow-Credentials:true');
-
$value = "something with cookie";
-
setcookie( "testcookie", $value, time() + 3600);
-
echo "cookie has seted";
注意: Access-Control-Allow-Origin必須制定特定的URL,不能是*, 且需要加上Access-Control-Allow-Credentials
第二步: 編寫請求測試代碼
在桌面上新建一個test.html文件,內容為:
-
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
-
<title>Document</title>
-
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
-
</head>
-
<body>
-
<script>
-
$.ajax({
-
url: "http://localhost:9000/",
-
type: 'GET',
-
success: function(data) {
-
console.log(data)
-
},
-
error: function(err) {
-
console.error(err)
-
}
-
})
-
</script>
-
</body>
-
</html>
- 在desktop目錄下起一個服務器,用php -S localhost:9999開啟一個本地服務器
第三步: 測試
1.在瀏覽器中訪問localhost:9999/test.html,打開調試工具->application->cookie可以看到cookie設置成功。
2.打開調試工具->netwoek,刷新一下,可以看到一個localhost請求,檢查這個localhost請求的Request Headers,發現沒有cookie這個頭部,說明不同源的請求時不會帶上cookie的(即使有CORS)
3.把test.html放到demo文件夾下,在訪問localhost:9000/test.html,查看Request Headers,會發現cookie頭部, 說明同源請求自動帶上了cookie
4.把test.html的內容更改為以下內容,請求時會有cookie頭部。說明withCredentials起作用了
-
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
-
<title>Document</title>
-
<script src="jquery-2.2.4.min.js"></script>
-
</head>
-
<body>
-
<script>
-
$.ajax({
-
url: "http://localhost:9000",
-
type: 'GET',
-
xhrFields: {
-
withCredentials: true // 這里設置了withCredentials
-
},
-
success: function(data) {
-
console.log(data)
-
},
-
error: function(err) {
-
console.error(err)
-
}
-
})
-
</script>
-
</body>
-
</html>
參考:https://zhuanlan.zhihu.com/p/28818954
https://www.zhihu.com/question/25427931
同源策略
http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
https://stackoverflow.com/questions/2870371/why-is-jquerys-ajax-method-not-sending-my-session-cookie
服務器也可以在設置Cookie的時候,指定Cookie的所屬域名為一級域名,比如.example.com。
Set-Cookie: key=value; domain=.example.com; path=/
這樣的話,二級域名和三級域名不用做任何設置,都可以讀取這個Cookie。
同源策略是瀏覽器最核心也最基本的安全功能首先:web是開放的世界, 需要互聯鏈接. 你的網站, 可以使用別人的圖片, img, 使用別人 script 做統計, 做廣告聯盟
假設沒有同源, 互聯網世界是什么樣?鏈接跳轉導致的問題. http://a.com , 放一個鏈接到 icbc.com, 然后 window.open來打開, 獲取窗口句柄, 然后可以擁有對這個頁面完全的控制權. 攔截表單,捕獲數據,將賬號密碼上傳到a.com.ajax請求, 要啥就有啥. 你登錄jd.com; 然后打開a.com, 通過ajax 請求http://jd.com 的用戶信息接口, 這時候因為訪問的jd.com,所以瀏覽器自動帶上了jd的cookie,然后獲取到你的訂單list ,昵稱, 所有私密信息.所以,需要要同源策略
在同一個域內,客戶端腳本可以任意讀寫同源內的資源,dom,cookie;但是不同的域,就不行.