cookie
、localStorage
、indexDB
DOM
Ajax
cookie
cookie
,是服務器端寫入瀏覽器端的小段信息,只有同源的網頁才能共享cookie
,一級域名相同但二級域名不一樣的網頁只要設置相同的document.domain
,就能夠共享cookiehtml
補充知識點:前端
qq.com
game.qq.com
、www.qq.com
、lol.qq.com
lpl.lol.qq.com
上述一段描述來自網上的文章,在此通過測試,提出了部分意見,關於意見是什麼,後面會提到,如今先證實上述描述的不精確性。nginx
驗證的服務器nginx
配置:ajax
server {
listen 8080;
server_name w1.gaopeng.com;
location / {
root /Users/gaopeng/Sites/w1.gaopeng.com;
index index.html index.htm;
}
}
server {
listen 8080;
server_name w2.gaopeng.com;
location / {
root /Users/gaopeng/Sites/w2.gaopeng.com;
index index.html index.htm;
}
}
複製代碼
在w1.gaopeng.com
、w2.gaopeng.com
文件夾下的index.html
內容json
<script>
document.domain = "gaopeng.com";
</script>
複製代碼
主要目的是設置相同的document.cookie
後端
瀏覽器打開w1.gaopeng.com
,發現document.domain
已經被設置gaopeng.com
,此時增長一個cookie
跨域
w2.gaopeng.com
發現
document.domain
已經被設置
gaopeng.com
,但依舊沒法獲取上述設置的
cookie
:
gao=peng
此時咱們看下cookie存在的表現: 瀏覽器
w1.gaopeng.com
設置的
cookie
的
Domain=w1.gaopeng.com
w2.gaopeng.com
依然沒有上述設置的
cookie
忽然想了一下若是將cookie設置爲二級域名會怎麼樣呢? 在w1.gaopeng.com
下,設置cookie
bash
w2.gaopeng.com
下,會獲取到剛剛設置的
cookie
再次觀察w1.gaopeng.com
、w2.gaopeng.com
的cookie
服務器
所以得出告終論,cookie
的共享與網站的是否同源並沒有明顯的關係,可否共享應該看cookie
自身的domain
,若是domain
相同,就能夠共享
猜測:存在兩個站點不一樣源(協議、端口不一樣)
A站:https://www.example.com:3443/
B站:http://www.example.com:3445/
因爲cookie
的domain
都是www.example.com
,那麼這兩個頁面的cookie
是能夠共享的
iframe
和window.open
只有同源的網頁才能獲取DOM,一級域名相同但二級域名不一樣的網頁只要設置相同的
document.domain
,就獲取DOM
// w1.gaopeng.com/index.html
index01.html
<iframe id="myIFrame" src="http://w2.gaopeng.com:8080/"></iframe>
<script>
// document.domain = 'gaopeng.com';
// 若是去掉註釋就能夠獲取到DOM
</script>
// w2.gaopeng.com/index.html
index02.html
<script>
document.domain = "gaopeng.com";
</script>
複製代碼
經過window.open
的實例:
利用上述方式的document.domain
等特性都沒法知足他們的通訊,能夠使用下面的介紹的通訊,方式,在文章最後會介紹localStorage
進行徹底不一樣源的網站之間的通訊。
徹底不一樣源的nginx
配置
server {
listen 8080;
server_name w2.gaopeng.com;
location / {
root /Users/gaopeng/Sites/w2.gaopeng.com;
index index.html index.htm;
}
}
server {
listen 8092;
server_name w2.gaopeng1.com;
location / {
root /Users/gaopeng/Sites/w2.gaopeng1.com;
index index.html index.htm;
}
}
複製代碼
在這裏因爲iframe
與window.open
的機理相似,因此只進行某一個種方式的演示
iframe
)片斷標識符是指URL
後面的#
號部分,若是隻是改變片斷標識符,頁面不會從新刷新。
父窗口能夠把信息,寫入子窗口的片斷標識符。
// w2.gaopeng1.com/index.html
index02.html
<button id='button'>改變hash</button>
<iframe id="myIFrame" src="http://w2.gaopeng1.com:8092/"></iframe>
<script>
var srcUrl = "http://w2.gaopeng1.com:8092/#" + "gao=peng"
document.getElementById('button').onclick = function () {
document.getElementById('myIFrame').src = srcUrl;
}
</script>
// w2.gaopeng1.com/index.html
demo03.html
<script>
window.onhashchange = checkMessage;
function checkMessage() {
var message = window.location.hash;
console.log('message', message);
}
</script>
複製代碼
如圖所示,當點擊改變hash按鈕時,iframe
頁面會檢測到hash
的變化執行checkMessage
方法
window.name
(iframe
)瀏覽器窗口有一個window.name
,這個屬性的最大特色是,不管是否同源,只要在同一個窗口裏,前一個網頁設置了這個屬性,後一個網頁能夠讀取它。
// w2.gaopeng1.com/index.html
index02.html
<iframe id="myIFrame" src="http://w2.gaopeng1.com:8092/"></iframe>
<script>
console.log(window.name);
</script>
// w2.gaopeng1.com/index.html
demo03.html
<script>
window.name = "gao=peng";
</script>
複製代碼
如圖所示,主窗口活動了子窗口設置的window.name
window.postMessage
(window.open
)上述的兩種方法都是投機取巧的方式,在HTML5中正式引入了:跨文檔通訊 API
// w2.gaopeng1.com/index.html
index02.html
<iframe id="myIFrame" src="http://w2.gaopeng1.com:8092/"></iframe>
<script>
// 獲取子窗口的引用
var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
win.postMessage(JSON.stringify({key: 'storage', data: obj}), 'http://w2.gaopeng1.com:8092/');
</script>
// w2.gaopeng1.com/index.html
demo03.html
<script>
window.onmessage = function(e) {
if (e.origin !== 'http://w2.gaopeng1.com:8092/') return;
var payload = JSON.parse(e.data);
switch (payload.method) {
case 'set':
localStorage.setItem(payload.key, JSON.stringify(payload.data));
break;
case 'get':
// 獲取父窗口的引用
var parent = window.parent;
var data = localStorage.getItem(payload.key);
parent.postMessage(data, 'http://w2.gaopeng.com:8080/');
break;
case 'remove':
localStorage.removeItem(payload.key);
break;
}
};
</script>
複製代碼
解決方案:
主要談論一下CORS
對cookie
的影響
ajax
會自動帶上同源的cookie
,不會帶上不一樣源的cookie
withCredentials
爲true
, 後端設置Header
的方式來讓ajax
自動帶上不一樣源的cookie
,可是這個屬性對同源請求沒有任何影響ajax
請求設置withCredentials
爲true
,注意: Access-Control-Allow-Origin
必須制定特定的URL,不能是*
, 且須要加上Access-Control-Allow-Credentials
前端代碼:// 客戶端也須要設置credentials: "include",否則服務端設置的cookie,也發送不過來
fetch("http://localhost:3000/post_form3", { method: "post", body: formData, credentials: "include" }).then(function(response) {
return response.json();
}).then(function(data) {
console.log(data);
}).catch(function(e) {
console.log(e);
});
複製代碼
後端代碼
app.all('*', function(req, res, next) {
// 若是想讓cookie發送至前端,必須設置爲localhost:4000,而不是*
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.header("Access-Control-Max-Age", 60); // 預檢請求的有效期
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods","PUT, POST, GET, DELETE, OPTIONS");
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
複製代碼
關於上述代碼中res.header("Access-Control-Max-Age", 60); // 預檢請求的有效期
,預檢請求能夠參考這篇文章