摘要:回調函數數據就是了,回調函數用來響應應該在頁面中調用的函數,數據則用來傳入要執行的回調函數。比如會得到小明這樣,里面的這個函數就能執行并且得到數據了。
由于安全的原因,瀏覽器做了很多方面的工作,由此也就引入了一系列的跨域問題,需要注意的是:
跨域并非瀏覽器限制了發起跨站請求,而是跨站請求可以正常發起,但是返回結果被瀏覽器攔截了。最好的例子是 crsf 跨站攻擊原理,請求是發送到了后端服務器無論是否跨域!注意:有些瀏覽器不允許從HTTPS的域跨域訪問HTTP,比如Chrome和Firefox,這些瀏覽器在請求還未發出的時候就會攔截請求,這是一個特例
1. JSONPJSONP的全稱是 "JSON With Padding", 詞面意思上理解就是 "填充式的JSON"。它不是一個新鮮的東西,隸屬于 JSON 的一種使用方法,或者說是一種使用模式,可以解決一些常見的瀏覽器端網頁跨域問題。
正如他的名稱一樣,它是指被包含在調用函數中的JSON,比如這樣:
callback({"Name": "小明", "Id" : 1823, "Rank": 7})
由于 jQuery 的一些原因,使得 JSONP 常常與 Ajax 混淆。實際上,他們沒有任何關系。
由于瀏覽器的同源策略,使得在網頁端出現了這個“跨域”的問題,然而我們發現,所有的 src 屬性并沒有受到相關的限制,比如 img / script 等。
JSONP 的原理就要從 script 說起。script 可以執行其他域的js 函數,比如這樣:
a.html ... ... b.js callback({url: "http://www.rccoder.net"})
顯然,上面的代碼是可以執行的,并且可以在console里面輸出http://www.rccoder.net
利用這一點,假如b.js里面的內容不是固定的,而是根據一些東西自動生成的, 嗯,這就是JSONP的主要原理了?;卣{函數+數據就是 JSON With Padding 了,回調函數用來響應應該在頁面中調用的函數,數據則用來傳入要執行的回調函數。
至于這個數據是怎么產生的,說粗魯點無非就是字符串拼接了。
簡單總結一下: Ajax 是利用 XMLHTTPRequest 來請求數據的,而它是不能請求不同域上的數據的。但是,在頁面上引用不同域的 js 文件卻是沒有任何問題的,這樣,利用異步的加載,請求一個 js 文件,而這個文件的內容是動態生成的(后臺語言字符串拼接出來的),里面包含的是 JSON With Padding(回調函數+數據),之前寫的那個函數就因為新加載進來的這段動態生成的 js 而執行,也就是獲取到了他要獲取的數據。
重復一下,在一個頁面中,a.html這樣寫,得到 UserId 為 1823 的信息:
a.html ... src="http://server2.example.com/RetrieveUser?UserId=1823&callback=parseResponse"> ...
請求這個地址會得到一個可以執行的 JavaScript。比如會得到:
parseResponse({"Name": "小明", "Id" : 1823, "Rank": 7})
這樣,a.html里面的 parseResponse() 這個函數就能執行并且得到數據了。
等等,jQuery到底做了什么:
jQuery 讓 JSONP 的使用API和Ajax的一模一樣:
$.ajax({ method: "jsonp", url: "http://server2.example.com/RetrieveUser?UserId=1823", success: function(data) { console.log(data) } })
之所以可以這樣是因為 jQuery 在背后傾注了心血,它會在執行的時候生成函數替換callback=dosomthing ,然后獲取到數據之后銷毀掉這個函數,起到一個臨時的代理器作用,這樣就拿到了數據。
JSONP 的后話:
JSONP的這種實現方式不受同源策略的影響,兼容性也很好;但是它之支持 GET 方式的清楚,只支持 HTTP 請求這種特殊的情況,對于兩個不同域之間兩個頁面的互相調用也是無能為力。
2. CORSXMLHttpRequest 的同源策略看起來是如此的{{BANNED}},即使是同一個公司的產品,也不可能完全在同一個域上面。還好,網絡設計者在設計的時候考略到了這一點,可以在服務器端進行一些定義,允許部分網絡訪問。
CORS 的全稱是 Cross-Origin Resource Sharing,即跨域資源共享。他的原理就是使用自定義的 HTTP 頭部,讓服務器與瀏覽器進行溝通,主要是通過設置響應頭的 Access-Control-Allow-Origin 來達到目的的。這樣,XMLHttpRequest 就能跨域了。
值得注意的是,正常情況下的 XMLHttpRequest 是只發送一次請求的,但是跨域問題下很可能是會發送兩次的請求(預發送)。
更加詳細的內容可以參見:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
CORS 的后話:
相比之下,CORS 就支持所有類型的 HTTP 請求了,但是在兼容上面,往往一些老的瀏覽器并不支持 CORS。
Desktop:
瀏覽器 | 版本 |
---|---|
Chrome | 4 |
Firefox (Gecko) | 3.5 |
Internet Explorer | 8 (via XDomainReques) 10 |
Opera | 12 |
Safari | 4 |
Mobile:
設備 | 版本 |
---|---|
Android | 2.1 |
Chrome for Android | yes |
Firefox Mobile (Gecko) | yes |
IE Mobile | ? |
Opera Mobile | 12 |
Safari Mobile | 3.2 |
window.name 在一個窗口(標簽)的生命周期之內是共享的,利用這點就可以傳輸一些數據。
除此之外,結合 iframe 還能實現更加強大的功能:
需要3個文件: a/proxy/b
a.html
b.html
proxy 是一個代理文件,空的就可以,需要和 a 在同一域下
4. document.domain在不同的子域 + iframe交互的時候,獲取到另外一個 iframe 的 window對象是沒有問題的,但是獲取到的這個window的方法和屬性大多數都是不能使用的。
這種現象可以借助document.domain 來解決。
example.com
1.example.com
這樣,就可以解決問題了。值得注意的是:document.domain 的設置是有限制的,只能設置為頁面本身或者更高一級的域名。
document.domain的后話:
利用這種方法是極其方便的,但是如果一個網站被攻擊之后另外一個網站很可能會引起安全漏洞。
5.location.hash這種方法可以把數據的變化顯示在 url 的 hash 里面。但是由于 chrome 和 IE 不允許修改parent.location.hash 的值,所以需要再加一層。
a.html 和 b.html 進行數據交換。
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 //模擬一個簡單的參數處理操作 switch(location.hash){ case "#paramdo": callBack(); break; case "#paramset": //do something…… break; } function callBack(){ try { parent.location.hash = "somedata"; } catch (e) { // ie、chrome的安全機制無法修改parent.location.hash, // 所以要利用一個中間域下的代理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 //因為parent.parent和自身屬于同一個域,所以可以改變其location.hash的值 parent.parent.location.hash = self.location.hash.substring(1);
這樣,利用中間的 c 層就可以用 hash 達到 a 與 b 的交互了。
6.window.postMessage()這個方法是 HTML5 的一個新特性,可以用來向其他所有的window對象發送消息。需要注意的是我們必須要保證所有的腳本執行完才發送MessageEvent,如果在函數執行的過程中調用了他,就會讓后面的函數超時無法執行。
參考資料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 倉庫~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78790.html
摘要:使用的方法假設要在和頁面之間傳遞數據頁面頁面參考鏈接下面談一下跨域訪問的一些安全性問題,主要是和攻擊問題。在跨域訪問中,注入主要是參數注入,如防止措施是對參數進行校驗過濾。 所謂跨域,或者異源,是指主機名(域名)、協議、端口號只要有其一不同,就為不同的域(或源)。瀏覽器中有一個基本的策略,叫同源策略,即限制源自A的腳本只能操作同源頁面的DOM。 先聊一下w3c的CORS規范:CORS旨...
摘要:歡迎來我的個人站點性能優化其他優化瀏覽器關鍵渲染路徑開啟性能優化之旅高性能滾動及頁面渲染優化理論寫法對壓縮率的影響唯快不破應用的個優化步驟進階鵝廠大神用直出實現網頁瞬開緩存網頁性能管理詳解寫給后端程序員的緩存原理介紹年底補課緩存機制優化動 歡迎來我的個人站點 性能優化 其他 優化瀏覽器關鍵渲染路徑 - 開啟性能優化之旅 高性能滾動 scroll 及頁面渲染優化 理論 | HTML寫法...
閱讀 2122·2021-11-22 15:24
閱讀 2410·2021-09-09 11:53
閱讀 3037·2021-09-04 16:40
閱讀 1636·2019-08-30 15:52
閱讀 3355·2019-08-29 13:47
閱讀 2735·2019-08-26 17:40
閱讀 1541·2019-08-26 13:24
閱讀 2245·2019-08-26 12:01