跨域與同源策略
目錄
- 跨域與同源策略
- 一、跨域
- 二、同源
一、跨域
1、什么是跨域
當一個請求url的協議、域名、埠三者之間任意一個與當前頁面url不同即為跨域
當前頁面url 被請求頁面url 是否跨域 原因
2、為什么會出現跨域問題
出于瀏覽器的同源策略限制,同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響,可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實作,同源策略會阻止一個域的javascript腳本和另外一個域的內容進行互動,所謂同源(即指在同一個域)就是兩個頁面具有相同的協議(protocol),主機(host)和埠號(port)
3、非同源限制
- 無法讀取非同源網頁的 Cookie、LocalStorage 和 IndexedDB
- 無法接觸非同源網頁的 DOM
- 無法向非同源地址發送 AJAX 請求
4、跨域解決方法
(1)設定document.domain解決無法讀取非同源網頁的 Cookie問題
因為瀏覽器是通過document.domain屬性來檢查兩個頁面是否同源,因此只要通過設定相同的document.domain,兩個頁面就可以共享Cookie(此方案僅限主域相同,子域不同的跨域應用場景,)
(2)跨檔案通信 API:window.postMessage()
呼叫postMessage方法實作父視窗http://test1.com向子視窗http://test2.com發訊息(子視窗同樣可以通過該方法發送訊息給父視窗)
它可用于解決以下方面的問題: - 頁面和其打開的新視窗的資料傳遞
- 多視窗之間訊息傳
- 頁面與嵌套的iframe訊息傳遞
- 上面三個場景的跨域資料傳遞
// 父視窗打開一個子視窗
var openWindow = window.open('http://test2.com', 'title');
// 父視窗向子視窗發訊息(第一個引數代表發送的內容,第二個引數代表接收訊息視窗的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');
呼叫message事件,監聽對方發送的訊息
// 監聽 message 訊息
window.addEventListener('message', function (e) {
console.log(e.source); // e.source 發送訊息的視窗
console.log(e.origin); // e.origin 訊息發向的網址
console.log(e.data); // e.data 發送的訊息
},false);
(3)JSONP
JSONP 是服務器與客戶端跨源通信的常用方法,最大特點就是簡單適用,兼容性好(兼容低版本IE),缺點是只支持get請求,不支持post請求,核心思想:網頁通過添加一個<script>元素,向服務器請求 JSON 資料,服務器收到請求后,將資料放在一個指定名字的回呼函式的引數位置傳回來
①原生實作
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服務器test.com發出請求,該請求的查詢字串有一個callback引數,用來指定回呼函式的名字
// 處理服務器回傳回呼函式的資料
<script type="text/javascript">
function dosomething(res){
// 處理獲得的資料
console.log(res.data)
}
</script>
② jQuery ajax
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
dataType: 'jsonp', // 請求方式為jsonp
jsonpCallback: "handleCallback", // 自定義回呼函式名
data: {}
});
(4)CORS
CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫,它是 W3C 標準,屬于跨源 AJAX 請求的根本解決方法
- 普通跨域請求:只需服務器端設定Access-Control-Allow-Origin
- 帶cookie跨域請求:前后端都需要進行設定
【前端設定】根據xhr.withCredentials欄位判斷是否帶有cookie
①原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端設定是否帶cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
②jQuery ajax
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true // 前端設定是否帶cookie
},
crossDomain: true, // 會讓請求頭中包含跨域的額外資訊,但不會含cookie
});
③axios
axios.defaults.withCredentials = true
【服務端設定】
服務器端對于CORS的支持,主要是通過設定Access-Control-Allow-Origin來進行的,如果瀏覽器檢測到相應的設定,就可以允許Ajax進行跨域的訪問
① Nodejs后臺
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {
var postData = '';
// 資料塊接收中
req.addListener('data', function(chunk) {
postData += chunk;
});
// 資料接收完畢
req.addListener('end', function() {
postData = qs.parse(postData);
// 跨域后臺設定
res.writeHead(200, {
'Access-Control-Allow-Credentials': 'true', // 后端允許發送Cookie
'Access-Control-Allow-Origin': 'http://www.domain1.com', // 允許訪問的域(協議+域名+埠)
'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly的作用是讓js無法讀取cookie
});
res.write(JSON.stringify(postData));
res.end();
});
});
server.listen('8080');
console.log('Server is running at port 8080...');
(5)websocket
Websocket 是 HTML5 的一個持久化的協議,它實作了瀏覽器與服務器的全雙工通信,同時也是跨域的一種解決方案,WebSocket 和 HTTP 都是應用層協議,都基于 TCP 協議,但是 WebSocket 是一種雙向通信協議,在建立連接之后,WebSocket 的 服務器與 客戶端都能主動向對方發送或接收資料,同時,WebSocket 在建立連接時需要借助 HTTP 協議,連接建立好了之后 client 與 server 之間的雙向通信就與 HTTP 無關了,
二、同源
1、源(origin):就是協議、域名和埠號
url中的源就是:http://www.company.com:80
若地址里面的協議、域名和埠號均相同則屬于同源
2、什么是同源策略
同源策略是瀏覽器的一個安全功能,不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方資源,所以a.com下的js腳本采用ajax讀取b.com里面的檔案資料是會報錯的
3、不受同源策略限制的
- 頁面中的鏈接,重定向以及表單提交是不會受到同源策略限制的
- 跨域資源的引入是可以的,但是js不能讀寫加載的內容,如嵌入到頁面中的
<script src="..."></script>,<img>,<link>,<iframe>等
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/297113.html
標籤:其他
上一篇:http新手詳細介紹(獨家學習筆記 全站最詳細明了)
下一篇:WebSocket協議介紹
