亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

淺談瀏覽器端JavaScript跨域解決方法

dantezhao / 2389人閱讀

摘要:回調(diào)函數(shù)數(shù)據(jù)就是了,回調(diào)函數(shù)用來響應(yīng)應(yīng)該在頁(yè)面中調(diào)用的函數(shù),數(shù)據(jù)則用來傳入要執(zhí)行的回調(diào)函數(shù)。比如會(huì)得到小明這樣,里面的這個(gè)函數(shù)就能執(zhí)行并且得到數(shù)據(jù)了。

由于安全的原因,瀏覽器做了很多方面的工作,由此也就引入了一系列的跨域問題,需要注意的是:

跨域并非瀏覽器限制了發(fā)起跨站請(qǐng)求,而是跨站請(qǐng)求可以正常發(fā)起,但是返回結(jié)果被瀏覽器攔截了。最好的例子是 crsf 跨站攻擊原理,請(qǐng)求是發(fā)送到了后端服務(wù)器無論是否跨域!注意:有些瀏覽器不允許從HTTPS的域跨域訪問HTTP,比如Chrome和Firefox,這些瀏覽器在請(qǐng)求還未發(fā)出的時(shí)候就會(huì)攔截請(qǐng)求,這是一個(gè)特例

1. JSONP

JSONP的全稱是 "JSON With Padding", 詞面意思上理解就是 "填充式的JSON"。它不是一個(gè)新鮮的東西,隸屬于 JSON 的一種使用方法,或者說是一種使用模式,可以解決一些常見的瀏覽器端網(wǎng)頁(yè)跨域問題。

正如他的名稱一樣,它是指被包含在調(diào)用函數(shù)中的JSON,比如這樣:

callback({"Name": "小明", "Id" : 1823, "Rank": 7})

由于 jQuery 的一些原因,使得 JSONP 常常與 Ajax 混淆。實(shí)際上,他們沒有任何關(guān)系。

由于瀏覽器的同源策略,使得在網(wǎng)頁(yè)端出現(xiàn)了這個(gè)“跨域”的問題,然而我們發(fā)現(xiàn),所有的 src 屬性并沒有受到相關(guān)的限制,比如 img / script 等。

JSONP 的原理就要從 script 說起。script 可以執(zhí)行其他域的js 函數(shù),比如這樣:

a.html
...



...


b.js
callback({url: "http://www.rccoder.net"})

顯然,上面的代碼是可以執(zhí)行的,并且可以在console里面輸出http://www.rccoder.net

利用這一點(diǎn),假如b.js里面的內(nèi)容不是固定的,而是根據(jù)一些東西自動(dòng)生成的, 嗯,這就是JSONP的主要原理了?;卣{(diào)函數(shù)+數(shù)據(jù)就是 JSON With Padding 了,回調(diào)函數(shù)用來響應(yīng)應(yīng)該在頁(yè)面中調(diào)用的函數(shù),數(shù)據(jù)則用來傳入要執(zhí)行的回調(diào)函數(shù)。

至于這個(gè)數(shù)據(jù)是怎么產(chǎn)生的,說粗魯點(diǎn)無非就是字符串拼接了。

簡(jiǎn)單總結(jié)一下: Ajax 是利用 XMLHTTPRequest 來請(qǐng)求數(shù)據(jù)的,而它是不能請(qǐng)求不同域上的數(shù)據(jù)的。但是,在頁(yè)面上引用不同域的 js 文件卻是沒有任何問題的,這樣,利用異步的加載,請(qǐng)求一個(gè) js 文件,而這個(gè)文件的內(nèi)容是動(dòng)態(tài)生成的(后臺(tái)語(yǔ)言字符串拼接出來的),里面包含的是 JSON With Padding(回調(diào)函數(shù)+數(shù)據(jù)),之前寫的那個(gè)函數(shù)就因?yàn)樾录虞d進(jìn)來的這段動(dòng)態(tài)生成的 js 而執(zhí)行,也就是獲取到了他要獲取的數(shù)據(jù)。

重復(fù)一下,在一個(gè)頁(yè)面中,a.html這樣寫,得到 UserId 為 1823 的信息:

a.html

...
src="http://server2.example.com/RetrieveUser?UserId=1823&callback=parseResponse">
...

請(qǐng)求這個(gè)地址會(huì)得到一個(gè)可以執(zhí)行的 JavaScript。比如會(huì)得到:

  parseResponse({"Name": "小明", "Id" : 1823, "Rank": 7})

這樣,a.html里面的 parseResponse() 這個(gè)函數(shù)就能執(zhí)行并且得到數(shù)據(jù)了。

等等,jQuery到底做了什么:

jQuery 讓 JSONP 的使用API和Ajax的一模一樣:

$.ajax({
  method: "jsonp",
  url: "http://server2.example.com/RetrieveUser?UserId=1823",
  success: function(data) {
    console.log(data)
  } 
})

之所以可以這樣是因?yàn)?jQuery 在背后傾注了心血,它會(huì)在執(zhí)行的時(shí)候生成函數(shù)替換callback=dosomthing ,然后獲取到數(shù)據(jù)之后銷毀掉這個(gè)函數(shù),起到一個(gè)臨時(shí)的代理器作用,這樣就拿到了數(shù)據(jù)。

JSONP 的后話

JSONP的這種實(shí)現(xiàn)方式不受同源策略的影響,兼容性也很好;但是它之支持 GET 方式的清楚,只支持 HTTP 請(qǐng)求這種特殊的情況,對(duì)于兩個(gè)不同域之間兩個(gè)頁(yè)面的互相調(diào)用也是無能為力。

2. CORS

XMLHttpRequest 的同源策略看起來是如此的{{BANNED}},即使是同一個(gè)公司的產(chǎn)品,也不可能完全在同一個(gè)域上面。還好,網(wǎng)絡(luò)設(shè)計(jì)者在設(shè)計(jì)的時(shí)候考略到了這一點(diǎn),可以在服務(wù)器端進(jìn)行一些定義,允許部分網(wǎng)絡(luò)訪問。

CORS 的全稱是 Cross-Origin Resource Sharing,即跨域資源共享。他的原理就是使用自定義的 HTTP 頭部,讓服務(wù)器與瀏覽器進(jìn)行溝通,主要是通過設(shè)置響應(yīng)頭的 Access-Control-Allow-Origin 來達(dá)到目的的。這樣,XMLHttpRequest 就能跨域了。

值得注意的是,正常情況下的 XMLHttpRequest 是只發(fā)送一次請(qǐng)求的,但是跨域問題下很可能是會(huì)發(fā)送兩次的請(qǐng)求(預(yù)發(fā)送)。

更加詳細(xì)的內(nèi)容可以參見:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

CORS 的后話:

相比之下,CORS 就支持所有類型的 HTTP 請(qǐng)求了,但是在兼容上面,往往一些老的瀏覽器并不支持 CORS。

Desktop:

瀏覽器 版本
Chrome 4
Firefox (Gecko) 3.5
Internet Explorer 8 (via XDomainReques) 10
Opera 12
Safari 4

Mobile:

設(shè)備 版本
Android 2.1
Chrome for Android yes
Firefox Mobile (Gecko) yes
IE Mobile ?
Opera Mobile 12
Safari Mobile 3.2
3. window.name

window.name 在一個(gè)窗口(標(biāo)簽)的生命周期之內(nèi)是共享的,利用這點(diǎn)就可以傳輸一些數(shù)據(jù)。

除此之外,結(jié)合 iframe 還能實(shí)現(xiàn)更加強(qiáng)大的功能:

需要3個(gè)文件: a/proxy/b

a.html

b.html

proxy 是一個(gè)代理文件,空的就可以,需要和 a 在同一域下

4. document.domain

在不同的子域 + iframe交互的時(shí)候,獲取到另外一個(gè) iframe 的 window對(duì)象是沒有問題的,但是獲取到的這個(gè)window的方法和屬性大多數(shù)都是不能使用的。

這種現(xiàn)象可以借助document.domain 來解決。

example.com


1.example.com

這樣,就可以解決問題了。值得注意的是:document.domain 的設(shè)置是有限制的,只能設(shè)置為頁(yè)面本身或者更高一級(jí)的域名。

document.domain的后話:

利用這種方法是極其方便的,但是如果一個(gè)網(wǎng)站被攻擊之后另外一個(gè)網(wǎng)站很可能會(huì)引起安全漏洞。

5.location.hash

這種方法可以把數(shù)據(jù)的變化顯示在 url 的 hash 里面。但是由于 chrome 和 IE 不允許修改parent.location.hash 的值,所以需要再加一層。

a.html 和 b.html 進(jìn)行數(shù)據(jù)交換。

a.html

function startRequest(){
    var ifr = document.createElement("iframe");
    ifr.style.display = "none";
    ifr.src = "http://2.com/b.html#paramdo";
    document.body.appendChild(ifr);
}

function checkHash() {
    try {
        var data = location.hash ? location.hash.substring(1) : "";
        if (console.log) {
            console.log("Now the data is "+data);
        }
    } catch(e) {};
}
setInterval(checkHash, 2000);
b.html

//模擬一個(gè)簡(jiǎn)單的參數(shù)處理操作
switch(location.hash){
    case "#paramdo":
        callBack();
        break;
    case "#paramset":
        //do something……
        break;
}

function callBack(){
    try {
        parent.location.hash = "somedata";
    } catch (e) {
        // ie、chrome的安全機(jī)制無法修改parent.location.hash,
        // 所以要利用一個(gè)中間域下的代理iframe
        var ifrproxy = document.createElement("iframe");
        ifrproxy.style.display = "none";
        ifrproxy.src = "http://3.com/c.html#somedata";    // 注意該文件在"a.com"域下
        document.body.appendChild(ifrproxy);
    }
}
c.html

//因?yàn)閜arent.parent和自身屬于同一個(gè)域,所以可以改變其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);

這樣,利用中間的 c 層就可以用 hash 達(dá)到 a 與 b 的交互了。

6.window.postMessage()

這個(gè)方法是 HTML5 的一個(gè)新特性,可以用來向其他所有的window對(duì)象發(fā)送消息。需要注意的是我們必須要保證所有的腳本執(zhí)行完才發(fā)送MessageEvent,如果在函數(shù)執(zhí)行的過程中調(diào)用了他,就會(huì)讓后面的函數(shù)超時(shí)無法執(zhí)行。

https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

參考資料

http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html

硬廣

原文地址: https://github.com/rccoder/blog/issues/5

歡迎 star 倉(cāng)庫(kù)~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/78790.html

相關(guān)文章

  • 淺談js跨域問題

    摘要:使用的方法假設(shè)要在和頁(yè)面之間傳遞數(shù)據(jù)頁(yè)面頁(yè)面參考鏈接下面談一下跨域訪問的一些安全性問題,主要是和攻擊問題。在跨域訪問中,注入主要是參數(shù)注入,如防止措施是對(duì)參數(shù)進(jìn)行校驗(yàn)過濾。 所謂跨域,或者異源,是指主機(jī)名(域名)、協(xié)議、端口號(hào)只要有其一不同,就為不同的域(或源)。瀏覽器中有一個(gè)基本的策略,叫同源策略,即限制源自A的腳本只能操作同源頁(yè)面的DOM。 先聊一下w3c的CORS規(guī)范:CORS旨...

    learn_shifeng 評(píng)論0 收藏0
  • 淺談跨域

    摘要:一什么是跨域跨域簡(jiǎn)單的理解就是同源策略的限制。同源策略限制的內(nèi)容請(qǐng)求不能正常進(jìn)行。同源策略默認(rèn)地址是網(wǎng)頁(yè)的本身。 一、什么是跨域? 跨域簡(jiǎn)單的理解就是JavaScript同源策略的限制。是出于安全的考慮,a.com域名下的js不能操作b.com或者c.com域名下的對(duì)象。 當(dāng)協(xié)議、子域名、主域名、端口號(hào)中任意一個(gè)不相同時(shí),都算作不同域。不同域之間相互請(qǐng)求資源,就算叫跨域。 一個(gè)正常...

    dunizb 評(píng)論0 收藏0
  • 2017文章總結(jié)

    摘要:歡迎來我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開緩存網(wǎng)頁(yè)性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫法...

    dailybird 評(píng)論0 收藏0
  • 2017文章總結(jié)

    摘要:歡迎來我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開緩存網(wǎng)頁(yè)性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫法...

    hellowoody 評(píng)論0 收藏0
  • 2017文章總結(jié)

    摘要:歡迎來我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開緩存網(wǎng)頁(yè)性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫法...

    wwolf 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<