摘要:瀏覽器端需要設(shè)置響應(yīng)頭的,,等字段,指定允許的方法,頭部,源等信息??梢酝ㄟ^(guò)前后端約定一個(gè)字段名,比如,來(lái)傳遞一個(gè)函數(shù)名,從而使得前端可以使用對(duì)應(yīng)的函數(shù),拿到數(shù)據(jù),處理數(shù)據(jù)。
原文地址:https://github.com/HolyZheng/...
了解幾個(gè)跨域的方案,并且通過(guò)簡(jiǎn)單實(shí)踐進(jìn)行體會(huì)。
如何實(shí)踐?但是,我們?nèi)绾芜M(jìn)行實(shí)踐呢?在哪發(fā)請(qǐng)求?向什么服務(wù)器發(fā)請(qǐng)求?很簡(jiǎn)單,就在當(dāng)前網(wǎng)頁(yè),打開(kāi)控制臺(tái),輸入請(qǐng)求的代碼
var url = "http://127.0.0.1:8888/"; var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.send();
那么我們就可以以當(dāng)前頁(yè)面url作為origin,向http://127.0.0.1:8888/ ,發(fā)送請(qǐng)求GET請(qǐng)求了。
同時(shí)在本地創(chuàng)建一個(gè)node服務(wù)
var http = require("http"); http.createServer(function (request, response) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("request success!!!"); }).listen(8888); console.log("Server running at http://127.0.0.1:8888/");
這樣我們就有服務(wù)器了,你可以很輕松的跟著這遍文章來(lái)實(shí)踐了,然后從當(dāng)前網(wǎng)頁(yè)發(fā)送get請(qǐng)求到本地服務(wù),理所當(dāng)然跨域了。
ps: github網(wǎng)站不行(本文最初再github上編寫(xiě)),會(huì)引發(fā)csp錯(cuò)誤,此錯(cuò)誤是用于防止內(nèi)容注入攻擊的,不得不說(shuō),大網(wǎng)站安全措施做得就是好,轉(zhuǎn)戰(zhàn)segmentfault做實(shí)踐。1. cors
cors(跨域資源共享 Cross-origin resource sharing),它允許瀏覽器向跨域服務(wù)器發(fā)出XMLHttpRequest請(qǐng)求,從而克服跨域問(wèn)題,它需要瀏覽器和服務(wù)器的同時(shí)支持。
cors 分為兩種請(qǐng)求,簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求,關(guān)于cors的更詳細(xì)介紹,推薦阮一峰老師的跨域資源共享 CORS 詳解,本文注重實(shí)踐。簡(jiǎn)單請(qǐng)求
正如上方的例子便是一個(gè)簡(jiǎn)單請(qǐng)求
var url = "http://127.0.0.1:8888/"; var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.send();
如何解決此案例的跨域問(wèn)題呢?
瀏覽器端,瀏覽器會(huì)自動(dòng)在請(qǐng)求頭中添加 origin 字段,我們不需要操作。
Request Headers: Origin: https://github.com
服務(wù)端,Access-Control-Allow-Origin屬性,我們需要服務(wù)端設(shè)置此屬性,指定允許的請(qǐng)求源域名,可以通過(guò)指定為 *來(lái)指定所以域名。后端動(dòng)起來(lái):
var http = require("http"); http.createServer(function (request, response) { response.writeHead(200, { "Content-Type": "text/plain", "Access-Control-Allow-Origin": "*" }); response.end("request success!!!"); }).listen(8888); console.log("Server running at http://127.0.0.1:8888/");
重啟服務(wù),再嘗試
這次沒(méi)有再報(bào)錯(cuò)了,我們看看服務(wù)器放回了什么
nice!跨域成功!
同樣我們?cè)诳刂婆_(tái)輸入一下代碼進(jìn)行put(非簡(jiǎn)單請(qǐng)求)
var url = "http://127.0.0.1:8888/"; var xhr = new XMLHttpRequest(); xhr.open("PUT", url, true); xhr.send();
毫無(wú)意外的報(bào)錯(cuò)
在進(jìn)行非簡(jiǎn)單請(qǐng)求的時(shí)候,瀏覽器會(huì)先發(fā)送一次OPTION請(qǐng)求來(lái)“預(yù)檢”(preflight)該請(qǐng)求是否被允許,請(qǐng)求頭中會(huì)通過(guò)Access-Control-Request-Method,Access-Control-Request-Headers來(lái)告訴服務(wù)器我需要用到的方法和字段,服務(wù)器通過(guò)返回的頭部信息中的Access-Control-Allow-Origin,Access-Control-Allow-Method來(lái)告訴瀏覽器該跨域請(qǐng)求是否被允許。修改后端代碼:
var http = require("http"); http.createServer(function (request, response) { response.writeHead(200, { "Content-Type": "text/plain", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT" }); response.end("request success!!!"); }).listen(8888); console.log("Server running at http://127.0.0.1:8888/");
可以看到瀏覽器會(huì)先發(fā)送一個(gè)預(yù)檢
當(dāng)確認(rèn)允許跨域之后,以后再發(fā)送該請(qǐng)求,就會(huì)省去預(yù)檢處理,之間當(dāng)作簡(jiǎn)單請(qǐng)求來(lái)操作。很明顯,修改了后端代碼后,這次的put請(qǐng)求時(shí)成功的。這里就不繼續(xù)上圖了。
cors總結(jié)cors(跨域資源共享 Cross-origin resource sharing),它允許瀏覽器向跨域服務(wù)器發(fā)出XMLHttpRequest請(qǐng)求,從而克服跨域問(wèn)題,它需要瀏覽器和服務(wù)器的同時(shí)支持。
瀏覽器端會(huì)自動(dòng)向請(qǐng)求頭添加origin字段,表明當(dāng)前請(qǐng)求來(lái)源。
瀏覽器端需要設(shè)置響應(yīng)頭的Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Allow-Origin等字段,指定允許的方法,頭部,源等信息。
請(qǐng)求分為簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求,非簡(jiǎn)單請(qǐng)求會(huì)先進(jìn)行一次OPTION方法進(jìn)行預(yù)檢,看是否允許當(dāng)前跨域請(qǐng)求。
2. jsonpjsonp的原理就是利用就是利用script標(biāo)簽沒(méi)有跨域限制,可以通過(guò)script標(biāo)簽的src屬性發(fā)送GET請(qǐng)求。我們繼續(xù)嘗試,先把后端有關(guān)跨域的設(shè)置去掉,并重啟服務(wù)
var http = require("http"); http.createServer(function (request, response) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("request success!!!"); }).listen(8888); console.log("Server running at http://127.0.0.1:8888/");
打開(kāi)我們的控制臺(tái)輸入一下代碼,利用script標(biāo)簽進(jìn)行jsonp請(qǐng)求
var script = document.createElement("script"); script.type = "text/javascript"; script.src = `http://127.0.0.1:8888/`; document.head.appendChild(script);
可以看到,后端正常的返回了
request success !!!
而且該請(qǐng)求為GET請(qǐng)求
Request URL: http://127.0.0.1:8888/ Request Method: GET Status Code: 200 OK Remote Address: 127.0.0.1:8888 Referrer Policy: no-referrer-when-downgrade
但是我們現(xiàn)在只是成功發(fā)送了一個(gè)跨域請(qǐng)求,但是我們不像XMLHttpRequest那樣可以在res.responseText中拿到數(shù)據(jù),通過(guò)jsonp我們?cè)撛趺茨玫秸?qǐng)求的數(shù)據(jù)呢?方法就是前后端約定一個(gè)callback字段名,來(lái)傳遞函數(shù)名,前端通過(guò)該函數(shù)來(lái)拿到數(shù)據(jù)。前端代碼修改為:
var script = document.createElement("script"); script.type = "text/javascript"; script.src = `http://127.0.0.1:8888/?callback=onBack`; document.head.appendChild(script); function onBack (res) { console.log(JSON.stringify(res)); // 請(qǐng)求完后刪除添加到頁(yè)面上的script標(biāo)簽 var head = document.head head.removeChild(script) }
通過(guò)callback字段來(lái)傳遞函數(shù)名onBack,后端代碼修改為
var http = require("http") var urlTool = require("url") // json 數(shù)據(jù) var data = {"methods": "jsonp", "result": "success"}; http.createServer(function (request, response) { var params = urlTool.parse(request.url, true) console.log(params) response.writeHead(200, { "Content-Type": "text/plain" }); if (params.query && params.query.callback) { // callback(data) var str = `${params.query.callback}(${JSON.stringify(data)})` } response.end(str); }).listen(8888); console.log("Server running at http://127.0.0.1:8888/");
重啟后端服務(wù),并且在控制臺(tái)輸入代碼,可以看到結(jié)果:
我們拿到了數(shù)據(jù),并且通過(guò)onBack函數(shù)將他輸出到了控制臺(tái)上!
總結(jié)jsonp是一種跨域方案,他利用script標(biāo)簽沒(méi)有跨域限制的特點(diǎn),通過(guò)script標(biāo)簽的的src屬性發(fā)送GET請(qǐng)求。
可以通過(guò)前后端約定一個(gè)字段名,比如callback,來(lái)傳遞一個(gè)函數(shù)名,從而使得前端可以使用對(duì)應(yīng)的callback函數(shù),拿到數(shù)據(jù),處理數(shù)據(jù)。
jsonp和cors比較CORS與JSONP的使用目的相同,但是比JSONP更強(qiáng)大。
JSONP只支持GET請(qǐng)求,CORS支持所有類型的HTTP請(qǐng)求。JSONP的優(yōu)勢(shì)在于支持老式瀏覽器,以及可以向不支持CORS的網(wǎng)站請(qǐng)求數(shù)據(jù)。
同源策略:同源策略限制了一個(gè)源(origin)中加載文本或腳本與來(lái)自其它源(origin)中資源的交互方式,這是一個(gè)用于隔離潛在惡意文件的重要安全機(jī)制。如果兩個(gè)頁(yè)面擁有 相同 的 協(xié)議(protocol),端口(如果指定),和 主機(jī),那么這兩個(gè)頁(yè)面就屬于同一個(gè)源(origin)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/95869.html
摘要:扯了這么多,自然不是為了吹水,而是要為了引出前端開(kāi)發(fā)的一個(gè)重要的知識(shí)點(diǎn)同源策略什么是同源策略出于保護(hù)用戶信息安全的目的,現(xiàn)在的瀏覽器都會(huì)實(shí)施同源策略這個(gè)政策,所謂同源策略指的是不同源的客戶端腳本在沒(méi)有明確授權(quán)情況下,不允許讀寫(xiě)對(duì)方的資源。 導(dǎo)語(yǔ)你家的小孩帶了他的朋友來(lái)你們的家里玩,你家的小孩如果要在自家屋里拿玩具玩、拿東西吃你自然是不會(huì)阻止,但是如果你家小孩的朋友人品不行,亂拿東西吃、...
摘要:扯了這么多,自然不是為了吹水,而是要為了引出前端開(kāi)發(fā)的一個(gè)重要的知識(shí)點(diǎn)同源策略什么是同源策略出于保護(hù)用戶信息安全的目的,現(xiàn)在的瀏覽器都會(huì)實(shí)施同源策略這個(gè)政策,所謂同源策略指的是不同源的客戶端腳本在沒(méi)有明確授權(quán)情況下,不允許讀寫(xiě)對(duì)方的資源。 導(dǎo)語(yǔ)你家的小孩帶了他的朋友來(lái)你們的家里玩,你家的小孩如果要在自家屋里拿玩具玩、拿東西吃你自然是不會(huì)阻止,但是如果你家小孩的朋友人品不行,亂拿東西吃、...
摘要:同源策略瀏覽器的一個(gè)安全功能,不同源的客戶端腳本在沒(méi)有明確授權(quán)的情況下,不能讀寫(xiě)對(duì)方資源。不受同源策略限制的跨域資源的引入是允許的頁(yè)面中的鏈接,重定向以及表單提交是不會(huì)受到同源策略限制的。1.什么是跨域資源請(qǐng)求? https://www.cnblogs.com/niuli1987/p/10252214.html 同源: 如果兩個(gè)頁(yè)面的協(xié)議,端口(如果有指定)和域名都相同,則兩個(gè)頁(yè)面具有相...
摘要:經(jīng)歷了幾場(chǎng)筆試面試,屢次被問(wèn)到關(guān)于如何實(shí)現(xiàn)跨域。轉(zhuǎn)自個(gè)人博客關(guān)于跨域什么是跨域一般來(lái)說(shuō),如果你在開(kāi)發(fā)中需要進(jìn)行跨域操作從一個(gè)非同源網(wǎng)站發(fā)送請(qǐng)求獲取數(shù)據(jù),一般而言,你在瀏覽器控制臺(tái)看到的結(jié)果為同源策略說(shuō)到跨域就不得不提同源策略。 前言 轉(zhuǎn)眼就是秋招季啦。經(jīng)歷了幾場(chǎng)筆試面試,屢次被問(wèn)到關(guān)于如何實(shí)現(xiàn)跨域。老實(shí)說(shuō),之前都是紙上談兵,也沒(méi)有項(xiàng)目需要跨域,甚至覺(jué)得這個(gè)東西沒(méi)什么意義。直到今天項(xiàng)目中...
閱讀 1531·2021-11-22 13:54
閱讀 4462·2021-09-22 15:56
閱讀 1887·2021-09-03 10:30
閱讀 1392·2021-09-03 10:30
閱讀 2134·2019-08-30 15:55
閱讀 1913·2019-08-30 14:13
閱讀 2133·2019-08-29 15:19
閱讀 2425·2019-08-28 18:13