跨域????如何解決

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.');
    });
});
相關文章
相關標籤/搜索