欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入分析Javascript跨域問題

 更新時間:2015年04月17日 10:18:25   投稿:hebedich  
JavaScript出于安全方面的考慮,不允許跨域調(diào)用其他頁面的對象。但在安全限制的同時也給注入iframe或是ajax應(yīng)用上帶來了不少麻煩。這里把涉及到跨域的一些問題簡單地整理一下

跨域是什么?

假設(shè)a.com/get.html需要獲取b.com/data.html中的數(shù)據(jù),而這里a.com和b.com并不是同一臺服務(wù)器,這就是跨域跨域會涉及到Javascript的同源策略,簡單來說就是為了保護(hù)網(wǎng)站的安全,不被外域(非同源)服務(wù)器的js修改本網(wǎng)站內(nèi)容。
引用一個表格,看一下引起跨因的條件有哪些:

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

1、JsonP

提到跨域不能不先提及jsonp。jsonp其實是JavacScript Object Notation with Padding的簡稱,可以理解成填充了內(nèi)容的json格式數(shù)據(jù)。
因為以上聲明了callback并且調(diào)用外域b.com的data.js,而data.js中調(diào)用:
callback({msg:"tqtan"});
這樣當(dāng)調(diào)用引用外域的js就會調(diào)用本地的callback()從而實現(xiàn)數(shù)據(jù)傳輸。
上面是只是簡單的跨域,我們來看jQuery的真正的運用。

jQuery中的ajax可拉取外域的數(shù)據(jù),通過兩種方法:

1、$.getJSON()

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

復(fù)制代碼 代碼如下:

假設(shè)上述請求訪問b.com下的servlet頁面,傳的參數(shù)為callback=?,jQuery會自動生成字符串填補占位符?,例如callback=jQuery17207481773362960666_1332575486681。這就聲明了與服務(wù)器的唯一標(biāo)示,服務(wù)器只需要返回帶有這個callback值的json格式數(shù)據(jù)即可,例如:

復(fù)制代碼 代碼如下:

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

這樣就能成功獲取非同源服務(wù)器的數(shù)據(jù)了。

2、$.ajax()

實現(xiàn)原理和上面一樣,只是可以自定義更多鏈接。

$.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形式請求服務(wù)器。

2、document.domain

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

//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來實現(xiàn)跨域。hash就是url#后面的內(nèi)容,例如http://targetkiller.net/index.html#data,這里#data就是hash。怎么用這個實現(xiàn)跨域呢?

還是那個例子,a.com/get.html需要獲取b.com/data.html,首先在get.html建立一個iframe,src還是指向data.html,后面帶上hash值實現(xiàn)傳參。另一端data.html根據(jù)獲取的hash作出響應(yīng),自身也創(chuàng)建一個iframe,src指向a.com/proxy.html,并把響應(yīng)數(shù)據(jù)添加到hash。之后,a.com/proxy.html只需要修改在同一a.com父域的get.html的hash即可。最后,怎樣獲取數(shù)據(jù)呢?只需要在get.html寫一個定時器setInterval,定期監(jiān)聽有無新的hash即可。

看到這里,你可能感到開始亂了,幾個問題:

1.proxy.html的作用?
由于get.html和data.html不在一個域上,所以不能修改location.hash值,于是運用proxy.html,先跳到找個代理頁面,然后通過parent.location.hash,也就是修改父親,讓兒子(get.html)也得到響應(yīng)。
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
//模擬一個簡單的參數(shù)處理操作
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創(chuàng)建一個iframe,src指向data.html,然后監(jiān)聽iframe的onload事件。與此同時,在data.html設(shè)置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,避免安全問題發(fā)生
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()優(yōu)雅地解決了跨域,也十分容易理解。
發(fā)送方調(diào)用postMessage()內(nèi)容,接受方監(jiān)聽onmessage接受內(nèi)容即可。
假設(shè)發(fā)送方為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);//發(fā)送源的window值
}
}, false);

6、CORS(后臺實現(xiàn))

以上5點都是前端實現(xiàn)的跨域,但是后臺參與會讓跨域更容易解決,也就是用CORS。
CORS是Cross-Origin Resource Sharing的簡稱,也就是跨域資源共享。它有多牛逼?之前說JsonP只能get請求,但CORS則可以接受所有類型的http請求,然而CORS只有現(xiàn)代瀏覽器才支持。
怎樣使用?前端只需要發(fā)普通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');
}

與此同時,服務(wù)器端只需要設(shè)置Access-Control-Allow-Origin頭即可。

java中你只需要設(shè)置

復(fù)制代碼 代碼如下:

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

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

相關(guān)文章

  • 微信小程序視頻彈幕發(fā)送功能的實現(xiàn)

    微信小程序視頻彈幕發(fā)送功能的實現(xiàn)

    這篇文章主要介紹了微信小程序視頻彈幕發(fā)送功能的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • window.print()打印根據(jù)高度設(shè)置居中顯示和布局(縱向橫向)

    window.print()打印根據(jù)高度設(shè)置居中顯示和布局(縱向橫向)

    本文主要介紹了window.print()打印根據(jù)高度設(shè)置居中顯示和布局(縱向橫向),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • JavaScript實現(xiàn)通過鍵盤彈鋼琴的效果實例代碼

    JavaScript實現(xiàn)通過鍵盤彈鋼琴的效果實例代碼

    這篇文章主要給大家介紹了關(guān)于JavaScript實現(xiàn)通過鍵盤彈鋼琴效果的相關(guān)資料,通過JS代碼實現(xiàn)了鋼琴鍵盤的交互效果,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • 分別用marquee和div+js實現(xiàn)首尾相連循環(huán)滾動效果,僅3行代碼

    分別用marquee和div+js實現(xiàn)首尾相連循環(huán)滾動效果,僅3行代碼

    這是本人2007年進(jìn)行的一項研究,當(dāng)時網(wǎng)絡(luò)上沒有什么既精簡又實用的循環(huán)滾動代碼,所以就自己琢磨了段時間,最終找到這個辦法
    2011-09-09
  • Bootstrap開發(fā)實戰(zhàn)之響應(yīng)式輪播圖

    Bootstrap開發(fā)實戰(zhàn)之響應(yīng)式輪播圖

    這篇文章主要為大家詳細(xì)介紹了Bootstrap開發(fā)實戰(zhàn)之響應(yīng)式輪播圖,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • js模擬類繼承小例子

    js模擬類繼承小例子

    使用js模擬類繼承小例子,學(xué)習(xí)js面向?qū)ο蟮呐笥芽梢詤⒖枷隆?/div> 2010-07-07
  • uniapp中刷新本頁面的三種方法

    uniapp中刷新本頁面的三種方法

    這篇文章主要給大家介紹了關(guān)于uniapp中刷新本頁面的三種方法,刷新頁面的具體邏輯可以根據(jù)實際需求進(jìn)行編寫,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • JS判斷輸入的字符串是否是數(shù)字的方法(正則表達(dá)式)

    JS判斷輸入的字符串是否是數(shù)字的方法(正則表達(dá)式)

    下面小編就為大家?guī)硪黄狫S判斷輸入的字符串是否是數(shù)字的方法(正則表達(dá)式)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • 用YUI做了個標(biāo)簽瀏覽效果

    用YUI做了個標(biāo)簽瀏覽效果

    用YUI做了個標(biāo)簽瀏覽效果...
    2007-02-02
  • 教你如何寫出可維護(hù)的JS代碼

    教你如何寫出可維護(hù)的JS代碼

    在平時工作開發(fā)中,大部分開發(fā)人員都花費大量的時間在維護(hù)其他人員的代碼。很難從頭開始開發(fā)新代碼,很多情況下都是以他人成果為基礎(chǔ)的,或者新增修改需求,自己寫的代碼也會被其他開發(fā)人員調(diào)用,所以寫好一份高質(zhì)量可維護(hù)的代碼就顯得十分重要。
    2021-05-05

最新評論