首頁 web前端 js教程 深入分析Javascript跨域問題_javascript技巧

深入分析Javascript跨域問題_javascript技巧

May 16, 2016 pm 04:03 PM
javascript 跨域問題

跨域是什麼?

假設a.com/get.html需要取得b.com/data.html中的數據,而這裡a.com和b.com並不是同一台伺服器,這就是跨網域跨域會涉及到Javascript的同源策略,簡單來說就是為了保護網站的安全,不被外域(非同源)伺服器的js修改本網站內容。
引用一張表格,看看造成跨因的條件有哪些:

但是有時候我們確實需要這麼做,那我們有哪些方法呢?

1、JsonP

提到跨域不能不先提及jsonp。 jsonp其實是JavacScript Object Notation with Padding的簡稱,可以理解成填入了內容的json格式資料。
因為以上宣告了callback並且呼叫外域b.com的data.js,而data.js中呼叫:
callback({msg:"tqtan"});
這樣當呼叫引用外域的js就會呼叫本地的callback()從而實現資料傳輸。
上面是只是簡單的跨域,我們來看jQuery的真正的運用。

jQuery中的ajax可拉取外域的數據,透過兩種方法:

1、$.getJSON()

這種方法簡單粗暴,請求外域Json。

複製程式碼 程式碼如下:

$.getJSON("http://b.com/dataServlet?callback=?",function(data){
console.log(data.msg);
});

假設上述請求訪問b.com下的servlet頁面,傳的參數為callback=?,jQuery會自動產生字串填補佔位符?,例如callback=jQuery17207481773362960666_1332575486681。這就聲明了與伺服器的唯一標示,伺服器只需要傳回帶有這個callback值的json格式資料即可,例如:

複製程式碼 程式碼如下:

//dataServlet.java
String callback = req.getParameter("callback");
PrintWriter out = resp.getWriter();
out.print(callback "('msg','tqtan')");

這樣就能成功取得非同源伺服器的資料了。

2、$.ajax()

實作原理和上面一樣,只是可以自訂更多連結。

$.ajax({
url:'http://b.com/dataServlet?words=hi',
dataType:'jsonp',
jsonp : 'jsoncallback',
jsoncallback : 'tqtan',
success:function(data){
console.log(data.msg);
},
error: function (e) {
console.log(e);
}
});
登入後複製

可以自訂callback的名字,這裡改為'tqtan',同時這裡可以傳值words=hi。
注意了,JsonP格式只能是以GET形式請求伺服器。

2、document.domain

這種方法只適用於主域相同,而子域不同的跨域。
也就是get.a.com和data.a.com的跨域問題,解決方法很簡單:
若get.a.com/get.html需要取得data.a.com/data.html的數據,首先在get.html插入一個iframe,src指向data.a.com/data.html,然後在data.html寫上document.domain='a.com';即可操縱data.html內的內容。

//get.html
var iframe = document.creatElement("iframe");
iframe.src="http://data.a.com/data.html";
iframe.style.display="none";
document.body.appendChild(iframe);
document.domain = 'a.com';
iframe.onload = function(){
var otherDocument = iframe.contentDocument || iframe.contentWindow.document;
//otherDocument就是另一个页面的document
//do whatever you want..
};
//data.html
document.domain = 'a.com';
登入後複製

3、url hash

你也可以透過url的hash來實現跨域。 hash就是url#後面的內容,例如http://targetkiller.net/index.html#data,這裡#data就是hash。怎麼用這個實現跨域呢?

還是那個例子,a.com/get.html需要取得b.com/data.html,首先在get.html建立一個iframe,src還是指向data.html,後面帶上hash值實作傳參。另一端data.html根據所取得的hash作出回應,本身也建立一個iframe,src指向a.com/proxy.html,並把回應資料加入hash。之後,a.com/proxy.html只需要修改在同一a.com父域的get.html的hash即可。最後,怎樣取得數據呢?只需要在get.html寫一個定時器setInterval,定期監聽有無新的hash即可。

看到這裡,你可能覺得開始亂了,幾個問題:

1.proxy.html的作用?
由於get.html和data.html不在一個網域上,所以不能修改location.hash值,於是運用proxy.html,先跳到找個代理頁面,然後透過parent.location.hash,也就是修改父親,讓兒子(get.html)也得到回應。
a.com/get.html

var iframe = document.createElement('iframe');
iframe.src = 'http://a.com/get.html#data';
iframe.style.display = 'none';
document.body.appendChild(iframe);
//周期检测hash更新
function getHash() {
var data = location.hash ? location.hash.substring(1) : '';
console.log(data);
}
var hashInt = setInterval(function(){getHash()}, 1000);
a.com/proxy.html
parent.location.hash = self.location.hash.substring(1);
b.com/data.html
//模拟一个简单的参数处理操作
if(location.hash){
var data = location.hash;
doSth(data);
}
function doSth(data){
console.log("from a.com:"+data);
var msg = "hello i am b.com";
var iframe = document.createElement('iframe');
iframe.src = "http://a.com/proxy.html#"+msg;
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
登入後複製

4、window.name

这种方法比较巧妙,引用圆心的解释,name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
具体例子依旧如上,同时也是需要一个代理页面。
a.com/get.html请求b.com/data.html,首先get.html创建一个iframe,src指向data.html,然后监听iframe的onload事件。与此同时,在data.html设置window.name = data;把window.name赋值。然后onload事件后马上把iframe的跳到本地a.com/proxy.html。因此window.name就共享到了src为proxy.html的找个iframe中,接下来,就是同源间获取值的事了。
a.com/get.html

var state = 0,
iframe = document.createElement('iframe'),
iframe.src = 'http://b.com/data.html";
iframe.style.display = 'none';
loadfn = function() {
if (state === 1) {
var data = iframe.contentWindow.name;
console.log(data);
} else if (state === 0) {
state = 1;
//跳到proxy.html
iframe.contentWindow.location = "http://a.com/proxy.html";
}
};
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload = loadfn;
}
document.body.appendChild(iframe);
a.com/proxy.html
// proxy.html的操作主要是删除get.html的iframe,避免安全问题发生
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
b.com/data.html
var data = "hello,tqtan";
window.name = data;
登入後複製

5、 postMessage()

html5的新方法postMessage()优雅地解决了跨域,也十分容易理解。
发送方调用postMessage()内容,接受方监听onmessage接受内容即可。
假设发送方为a.com/send.html,接受方为b.com/receive.html。
a.com/send.html

var iframe = document.createElement("iframe");
iframe.src = "http://b.com/receive.html";
document.body.appendChild(iframe);
iframe.contentWindow.postMessage("hello","http://b.com");
b.com/receive.html
window.addEventListener('message', function(event){
// 通过origin属性判断消息来源地址
if (event.origin == 'http://a.com') {
console.log(event.data);
console.log(event.source);//发送源的window值
}
}, false);
登入後複製

6、CORS(后台实现)

以上5点都是前端实现的跨域,但是后台参与会让跨域更容易解决,也就是用CORS。
CORS是Cross-Origin Resource Sharing的简称,也就是跨域资源共享。它有多牛逼?之前说JsonP只能get请求,但CORS则可以接受所有类型的http请求,然而CORS只有现代浏览器才支持。
怎样使用?前端只需要发普通ajax请求,注意检测CORS的支持度。引用自蒋宇捷。

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');
}
登入後複製

与此同时,服务器端只需要设置Access-Control-Allow-Origin头即可。

java中你只需要设置

复制代码 代码如下:

response.setHeader("Access-Control-Allow-Origin", "*");

为了安全,也可以将*改为特定域名,例如a.com。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles