首頁  >  文章  >  web前端  >  什麼是跨域? javascript跨域的四種方式介紹

什麼是跨域? javascript跨域的四種方式介紹

不言
不言轉載
2018-10-22 13:54:1312926瀏覽

這篇文章帶給大家的內容是關於php協成實現的詳解(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

一、什麼是跨域

什麼是跨域? javascript跨域的四種方式介紹

#JavaScript出於安全性方面的考慮,不允許跨域呼叫其他頁面的物件。那什麼是跨域呢,簡單理解就是因為JavaScript同源策略的限制,a.com網域下的js無法操作b.com或c.a.com網域下的物件。
當協定、子網域、主網域、連接埠號碼中任一個不相同時,都算是不同網域。不同域之間互相請求資源,就算是「跨域」。
例如:http://www.abc.com/index.html 請求 http://www.efg.com/service.php。

有一點必須要注意:跨域並不是請求發不出去,請求能發出去,服務端能收到請求並正常返回結果,只是結果被瀏覽器攔截了 。之所以會跨域,是因為受到了同源策略的限制,同源策略要求源相同才能正常進行通信,即協議、域名、端口號都完全一致。

大家可以參考下圖,有助於深入理解跨域。

什麼是跨域? javascript跨域的四種方式介紹

特別說明兩點:

#第一:如果是協定和連接埠造成的跨域問題「前台」是無能為力的。

第二:在跨域問題上,域只是透過「URL的首部」來識別而不會根據網域對應的IP位址是否相同來判斷。 「URL的首部」可以理解為「協定, 網域名稱和連接埠必須匹配」。

二、什麼是同源策略及其限制

同源策略限制從一個來源載入的文件或腳本如何與來自另一個來源的資源互動。這是一個用於隔離潛在惡意檔案的關鍵的安全機制。它的存在可以保護使用者隱私訊息,防止身分偽造等(讀取Cookie)。

同源策略限制內容有:

  • Cookie、LocalStorage、IndexedDB 等儲存性內容

  • DOM 節點

  • AJAX 請求不能傳送

#但有三個標籤是允許跨網域載入資源:

1.<img  alt="什麼是跨域? javascript跨域的四種方式介紹" >
2.<link>
3.<script></script>

接下來我們討論下有哪些處理跨域的方法。但所有的跨域都必須經過資訊提供方的允許。如果未經允許即可獲取,那是瀏覽器同源策略出現漏洞。

三、處理跨域方法一-JSONP

1.JSONP原理

利用<script></script> 元素的這個開放策略,網頁可以得到從其他來源動態產生的JSON 資料。 JSONP請求一定需要對方的伺服器做支援才可以。

2.JSONP和AJAX比較

JSONP和AJAX相同,都是客戶端傳送請求,從伺服器端取得資料的方式到伺服器端。但AJAX屬於同源策略,JSONP屬於非同源策略(跨域請求)

3.JSONP優缺點

JSONP優點是相容性好,可用於解決主流瀏覽器的跨域資料存取的問題。 缺點是僅支援get方法具有限制。

4.JSONP的流程(以第三方API位址為例,不必考慮後台程式)

  • 宣告一個回呼函數,其函數名稱(如fn)當做參數值,要傳遞給跨域請求資料的伺服器,函數形參為要取得目標資料(伺服器傳回的data)。

  • 建立一個<script></script>標籤,把那個跨域的API資料介面位址,賦值給script的src,還要在這個位址中向伺服器傳遞該函數名(可以透過問號傳參:?callback=fn)。

    • 伺服器接收到請求後,需要進行特殊的處理:把傳遞進來的函數名稱和它需要給你的資料拼接成一個字串,例如:傳遞進去的函數名稱是fn,它所準備的資料是fn([{"name":"jianshu"}])。

  • 最後伺服器把準備的資料透過HTTP協定傳回給客戶端,客戶端再呼叫執行先前宣告的回呼函數(fn),對傳回的資料進行操作。

<script>
    function fn(data) {
        alert(data.msg);
    }
</script>
<script></script>

其中 fn 是客戶端註冊的回呼的函數,目的取得跨網域伺服器上的json資料後,資料在處理中。
最後伺服器傳回給客戶端資料的格式為:

fn({ msg:'this  is  json  data'})

5.jQuery的jsonp形式

JSONP都是GET和非同步請求的,不存在其他的請求方式和同步請求,且jQuery預設就會給JSONP的請求清除快取。

$.ajax({
url:"http://crossdomain.com/jsonServerResponse",
dataType:"jsonp",
type:"get",//可以省略
jsonpCallback:"fn",//->自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略
jsonp:"jsonp",//->把传递函数名的那个形参callback变为jsonp,可省略
success:function (data){
console.log(data);}
});

四、處理跨域方法二-CORS

#

1.CORS原理

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信

2.CORS优缺点

CORS要求浏览器(>IE10)和服务器的同时支持,是跨域的根本解决方法,由浏览器自动完成
优点在于功能更加强大支持各种HTTP Method,缺点是兼容性不如JSONP。
只需要在服务器端做一些小小的改造即可:

header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods:POST,GET");

例如:网站http://localhost:63342/ 页面要请求http://localhost:3000/users/userlist  页面,userlist页面返回json字符串格{name: 'Mr.Cao', gender: 'male', career: 'IT Education'}

//在服务器端设置同源策略地址
router.get("/userlist", function (req, res, next) {   
    var user = {name: 'Mr.Cao', gender: 'male', career: 'IT Education'};  
    res.writeHeader(200,{"Access-Control-Allow-Origin":'http://localhost:63342'});  
    res.write(JSON.stringify(user));  
    res.end();  
});

在响应头上添加Access-Control-Allow-Origin属性,指定同源策略的地址。同源策略默认地址是网页的本身。只要浏览器检测到响应头带上了CORS,并且允许的源包括了本网站,那么就不会拦截请求响应

什麼是跨域? javascript跨域的四種方式介紹

五、处理跨域方法三——WebSocket

Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

//前端代码:
<p>user input:<input></p>
<script></script>
<script>
var socket = io(&#39;http://www.domain2.com:8080&#39;);
// 连接成功处理
socket.on(&#39;connect&#39;, function() {
    // 监听服务端消息
    socket.on(&#39;message&#39;, function(msg) {
        console.log(&#39;data from server: ---> &#39; + msg); 
    });

 // 监听服务端关闭
    socket.on(&#39;disconnect&#39;, function() { 
        console.log(&#39;Server socket has closed.&#39;); 
    });
});
document.getElementsByTagName(&#39;input&#39;)[0].onblur = function() {
    socket.send(this.value);
};
</script>
//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.'); 
    });
});

六、处理跨域方法四——postMessage

如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。

接下来我们看个例子:
http://localhost:63342/index.html页面向http://localhost:3000/message.html传递“跨域请求信息”

//发送信息页面 http://localhost:63342/index.html
  
  
    <meta>  
    <title>跨域请求</title>   
  
  
    <iframe></iframe>  
    <input>  
  
  
<script>  
   function  run(){  
        var frm=document.getElementById("frm");  
        frm.contentWindow.postMessage("跨域请求信息","http://localhost:3000");  
   }  
</script>
//接收信息页面 http://localhost:3000/message.html
 window.addEventListener("message",function(e){  //通过监听message事件,可以监听对方发送的消息。
  console.log(e.data);  
},false);

以上是什麼是跨域? javascript跨域的四種方式介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除