国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

深入分析Javascript跨域問題

2019-11-20 12:38:30
字體:
來源:轉載
供稿:網友

跨域是什么?

假設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。

復制代碼 代碼如下:

假設上述請求訪問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.htmlvar 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.htmldocument.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.htmlparent.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.htmliframe.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.htmlvar 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.htmlwindow.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 {// 否則,瀏覽器不支持CORSxhr = 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。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 慈利县| 南靖县| 湘乡市| 建阳市| 高青县| 河北区| 伊通| 木里| 无为县| 怀柔区| 大英县| 芜湖市| 陵川县| 共和县| 大田县| 浪卡子县| 渭源县| 德保县| 武定县| 南皮县| 拜城县| 乌鲁木齐市| 霸州市| 泰顺县| 金坛市| 南和县| 绥江县| 星子县| 北流市| 大兴区| 霸州市| 合川市| 密云县| 徐汇区| 宜昌市| 石渠县| 德清县| 陵水| 肥东县| 木里| 东至县|