摘要:關(guān)于跨域?yàn)槭裁磿?huì)有跨域我們得先了解下同源策略。簡(jiǎn)而言之,同協(xié)議同域名同端口號(hào)什么是跨域跨域就是采取技術(shù)方案突破同源策略的限制,實(shí)現(xiàn)不同域之間交互請(qǐng)求響應(yīng)。
關(guān)于跨域 why?
為什么會(huì)有跨域?
我們得先了解下 ==同源策略(SOP, Same Origin Policy)==。
瀏覽器出于安全方面的考慮,只能訪(fǎng)問(wèn)與包含它的頁(yè)面位于同一個(gè)域中的資源,該策略為通信設(shè)置了“相同的協(xié)議、相同的域、相同的端口”這一限制。試圖訪(fǎng)問(wèn)上述限制之外的資源,都會(huì)引發(fā)安全錯(cuò)誤。這種安全策略可以預(yù)防某些惡意行為。
簡(jiǎn)而言之,
同協(xié)議 Same Protocol
同域名 Same Hostname
同端口號(hào) Same Port
Same Protocol && Same Hostname && Same Port
What?什么是跨域?
==跨域就是采取技術(shù)方案突破同源策略的限制,實(shí)現(xiàn)不同域之間交互(請(qǐng)求響應(yīng))。==
How?那么如何實(shí)現(xiàn)跨域呢?
有以下幾種方法。
==方法一==
CORS (Cross-Origin Resource Sharing,跨域源資源共享),是一種ajax跨域請(qǐng)求資源的方式,支持現(xiàn)代瀏覽器,IE支持10以上,通過(guò)XMLHttpRequest實(shí)現(xiàn)Ajax通信的一個(gè)主要限制就是同源策略。
CORS是W3C的一個(gè)工作草案,定義了在必須訪(fǎng)問(wèn)跨境資源時(shí),瀏覽器和服務(wù)器該如何溝通。CORS的基本思想,就時(shí)使用自定義的HTTP頭部讓瀏覽器和服務(wù)器進(jìn)行溝通,從而決定請(qǐng)求或者響應(yīng)應(yīng)該成功還是失敗。
實(shí)現(xiàn)思路:使用XMLHttpRequest發(fā)送請(qǐng)求時(shí),瀏覽器會(huì)給該請(qǐng)求自動(dòng)添加一個(gè)請(qǐng)求頭:Origin。服務(wù)器經(jīng)過(guò)一系列處理,如果確定請(qǐng)求來(lái)源頁(yè)面屬于白名單,則在響應(yīng)頭部加入首部字段:Access-Control-Allow-Origin。瀏覽器比較請(qǐng)求頭部的Origin 和響應(yīng)頭部的 Access-Control-Allow-Origin是否一致,一致的話(huà),瀏覽器得到響應(yīng)數(shù)據(jù)。如果服務(wù)器沒(méi)有設(shè)置Access-Control-Allow-Origin 或者這個(gè)頭部源信息不匹配,瀏覽器就會(huì)駁回請(qǐng)求。
模擬CORS的實(shí)現(xiàn)
步驟1.
如何偽裝一個(gè)網(wǎng)站(在本地)?
1.編輯hosts文件
蘋(píng)果mac: 直接在git bash上輸入命令行操作即可 “sudo vi /etc.hosts” ,或者下載一些圖形界面應(yīng)用軟件直接修改。
Windows操作系統(tǒng):
win鍵(四個(gè)方塊的鍵)+ R = 彈開(kāi)運(yùn)行窗口
復(fù)制該文件路徑 c:windowssystem32driversetc
選中hosts文件,右鍵-屬性-安全-選擇組或用戶(hù)名(添加修改保存的權(quán)限的對(duì)象)- 編輯 - 再次選擇組或用戶(hù)名(添加修改保存的權(quán)限的對(duì)象 - 勾選權(quán)限(選項(xiàng)在此不表)
打開(kāi)hosts文件,寫(xiě)入 127.0.0.1 localhost;127.0.0.1 bai.com;127.0.0.1 google.com;可以寫(xiě)入你任何你想模擬的網(wǎng)站,按照這種對(duì)應(yīng)關(guān)系格式即可, ip地址+域名。
步驟2.
所需工具
node.js && git bash(模擬服務(wù)器),一個(gè)簡(jiǎn)單的html頁(yè)面里面有個(gè)跨域請(qǐng)求的Ajax通信。
hello world
//nodeJS模擬后端響應(yīng)CORS的實(shí)現(xiàn) var http = require("http"); var fs = require("fs"); var url = require("url"); var path = require("path"); http.createServer(function(req, res){ var urlObj = url.parse(req.url, true) switch (urlObj.pathname){ case "/getNews": var news = ["NBA Break News","CBA Break News"] //CORS的實(shí)現(xiàn) res.setHeader("Access-Control-Allow-Origin","http://google.com:8080") /*res.setHeader("Access-Control-Allow-Origin","*") 服務(wù)器設(shè)置公用接口 */ res.end(JSON.stringify(news)); break; case "/" : if(urlObj.pathname == "/") { urlObj.pathname += "index.html" } default: var filePath = path.join(__dirname, urlObj.pathname); fs.readFile(filePath,"binary", function(error, fileContent){ if(error){ console.log("404") res.writeHeader(404, "not found") res.end("404,not found
") }else { res.write(fileContent, "binary") } }) } }).listen(8080);
上面代碼就是CORS實(shí)現(xiàn)的過(guò)程。
在本地修改hosts文件,127.0.0.1 google.com, 頁(yè)面的url為 http://google.com:8080。
在title為google的頁(yè)面上添加一個(gè)ajax請(qǐng)求,該請(qǐng)求以get方法會(huì)向baiduServer的端口("http://baidu.com:8080/getNews")發(fā)送一個(gè)請(qǐng)求。
瀏覽器會(huì)給請(qǐng)求頭加上Origin: http://google.com:8080, Request URL: http://baidu.com:8080/getNews。
baiduServer后端,響應(yīng)頭添加首部字段。Access-Control-Allow-Origin: http://google.com:8080。 表明該服務(wù)器(baiduServer)接受請(qǐng)求并給予響應(yīng)。
瀏覽器比較請(qǐng)求頭部的Origin 和響應(yīng)頭部的 Access-Control-Allow-Origin是否一致,一致的話(huà),瀏覽器得到響應(yīng)數(shù)據(jù)。如果服務(wù)器沒(méi)有設(shè)置Access-Control-Allow-Origin: http://google.com:8080 或者這個(gè)頭部源信息不匹配,瀏覽器就會(huì)駁回請(qǐng)求。
當(dāng)然服務(wù)器也可以設(shè)置公用接口, res.setHeader("Access-Control-Allow-Origin","*")
服務(wù)器設(shè)置公用接口, 任何人都可以使用該服務(wù)器這個(gè)端口的數(shù)據(jù)。
==方法二==
JSONP,是JSON with padding的簡(jiǎn)寫(xiě)(填充式JSON或參數(shù)式JSON)。
JSONP的原理,通過(guò)動(dòng)態(tài) -->