1.什麼是跨域
當一個請求url的協議、域名、端口三者之間任意一個與當前的url不一樣即爲跨域
ex:
http//www.... 和https//www....就是協議上的跨域(http/https)
www.baidu.com 和www.test.com 就是主域名不一樣(baidu/test)
www.test.com 和blog.test.com 就是子域名不一樣(WWW/blog)
www.test.com:8080 和www.test.com:7000 端口上的跨域(8080/7000)
2.爲何瀏覽器會禁止跨域
由於跨域的訪問會帶來許多安全性上的問題,cookie通常都用於狀態控制,存儲登陸的信息,若是容許跨域,那麼別的網站用一段腳本就能夠輕鬆獲取你的cookie數據,而且冒充身份去登陸網站(這不一下就被盜號了嗎),存在極大的安全隱患,因此,如今的瀏覽器都採用同源策略
3.非同源限制
1.沒法讀取非同源網頁的Cookie、Localstorage和indexedDB
2.沒法接觸非同源網頁的DOM節點
3.沒法向非同源地址發送ajax請求
注:有三個標籤容許跨域加載資源
1.<img src='xxx'>
2.<link href='xxx'>
3.<script src='xxx'>
4.如何解決跨域訪問問題
1.document.domain
兩個頁面能夠經過設置相同的document.domain,由於瀏覽器是經過document.domain屬性來檢查兩個網頁是否同源
使用:兩個網頁都設置document.domain='test.com' #不是固定的,本身想名字噢
缺點:這方式的侷限性比較大,由於只能用於二級域名相同的狀況下,好比說,a.test.com 和 b.test.com 適用該方式
2.JSONP
利用<script>元素的開放策略,向服務器請求 JSON 數據,服務器收到請求後,將數據放在一個指定名字的回調函數的參數位置傳回來。
與ajax的區別:
JSONP和ajax相同,都是客戶端向服務器端發送請求,從服務器端獲取數據的方式。但ajax屬於同源策略,JSONP屬於非同源策略(跨域請求)
優勢:兼容性好
缺點:只支持get,不支持post
使用:
1.聲明一個回調函數,其函數名(如fn)當作參數值,要傳遞給跨域請求數據的服務器,函數形參爲要獲取目標數據(服務器返回的data)。
2.建立一個<script>標籤,把那個跨域的API數據接口地址,賦值給script的src,還要在這個地址中向服務器傳遞該函數名(能夠經過問號傳參:?callback=fn)。
3.服務器接收到請求後,須要進行特殊的處理:把傳遞進來的函數名和它須要給你的數據拼接成一個字符串,例如:傳遞進去的函數名是fn,它準備好的數據是fn([{"name":"jianshu"}])。
4.最後服務器把準備的數據經過HTTP協議返回給客戶端,客戶端再調用執行以前聲明的回調函數(fn),對返回的數據進行操做。
<script type="text/javascript"src="http://crossdomain.com/jsonServerResponse?jsonp=fn"> </script>
<script type="text/javascript">
function fn(data){
//處理得到的數據
}
</script>
其中 fn 是客戶端註冊的回調的函數,目的獲取跨域服務器上的json數據後,對數據進行在處理。
最後服務器返回給客戶端數據的格式爲:
fn({ msg:'this is json data'})
3.CORS
CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫。它是 W3C 標準,屬於跨源 AJAX 請求的根本解決方法。整個CORS通訊過程都是瀏覽器自動完成的,不須要用戶參與,瀏覽器一旦發現AJAX請求跨源,會自動添加一些附加的頭信息,有時還會多出一次附加的請求,用戶不會有感受,所以,實現CORS通訊的關鍵是服務器,只要服務器實現了CORS接口,就能夠跨源通訊
優勢:功能更增強大支持各類HTTP Method
缺點:兼容性不如JSONP
使用:
1.前端代碼(須要判斷瀏覽器是否支持狀況)
function createCORSRequest(method, url) {var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// 此時即支持CORS的狀況
// 檢查XMLHttpRequest對象是否有「withCredentials」屬性
// 「withCredentials」僅存在於XMLHTTPRequest2對象裏
xhr.open(method, url, true);
} else if (typeof!= "undefined") {
// 不然檢查是否支持XDomainRequest,IE8和IE9支持
// XDomainRequest僅存在於IE中,是IE用於支持CORS請求的方式
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// 不然,瀏覽器不支持CORS
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
服務器:
Apache須要使用mod_headers模塊來激活HTTP頭的設置,它默認是激活的。你只須要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入如下內容便可
Header set Access-Control-Allow-Origin *
4.跨文檔通訊 API:window.postMessage()
調用postMessage方法實現父窗口http://test1.com向子窗口http://test2.com發消息(子窗口一樣能夠經過該方法發送消息給父窗口)
// 父窗口打開一個子窗口
var openWindow = window.open('http://test2.com', 'title');
// 父窗口向子窗口發消息(第一個參數表明發送的內容,第二個參數表明接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');
// 監聽 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);
5.WebSocket
Websocket是HTML5的一個持久化的協議,它實現了瀏覽器與服務器的全雙工通訊,同時也是跨域的一種解決方案。WebSocket和HTTP都是應用層協議,都基於 TCP 協議。可是 WebSocket 是一種雙向通訊協議,在創建鏈接以後,WebSocket 的 server 與 client 都能主動向對方發送或接收數據。同時,WebSocket 在創建鏈接時須要藉助 HTTP 協議,鏈接創建好了以後 client 與 server 之間的雙向通訊就與 HTTP 無關了。
原生WebSocket API使用起來不太方便,咱們使用Socket.io,它很好地封裝了webSocket接口,提供了更簡單、靈活的接口,也對不支持webSocket的瀏覽器提供了向下兼容。
1.前端代碼
<div>user input:<input type="text"></div>
<script src="./socket.io.js"></script>
<script> var socket = io('http://www.domain2.com:8080'); // 鏈接成功處理
socket.on('connect', function () {
// 監聽服務端消息
socket.on('message', function (msg) {
console.log('data from server: ---> ' + msg);
});
// 監聽服務端關閉
socket.on('disconnect', function () {
console.log('Server socket has closed.');
});
});
document.getElementsByTagName('input')[0].onblur = function () {
socket.send(this.value);
}; </script>
2.Nodejs socket後臺:
var http = require('http');
var socket = require('socket.io');
// 啓http服務
var server = http.createServer(function (req, res) {
res.writeHead(200, {'Content-type': 'text/html'});
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');
// 監聽socket鏈接
socket.listen(server).on('connection', function (client) {
// 接收信息
client.on('message', function (msg) {
client.send('hello:' + msg);
console.log('data from client: ---> ' + msg);
});
// 斷開處理
client.on('disconnect', function () {
console.log('Client socket has closed.');
});
});