原文地址: https://github.com/HolyZheng/...
瞭解幾個跨域的方案,而且經過簡單實踐進行體會。javascript
可是,咱們如何進行實踐呢?在哪發請求?向什麼服務器發請求?很簡單,就在當前網頁,打開控制檯,輸入請求的代碼html
var url = 'http://127.0.0.1:8888/'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.send();
那麼咱們就能夠以當前頁面url做爲origin,向http://127.0.0.1:8888/ ,發送請求GET請求了。
同時在本地建立一個node服務前端
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/');
這樣咱們就有服務器了,你能夠很輕鬆的跟着這遍文章來實踐了,而後從當前網頁發送get請求到本地服務,理所固然跨域了。java
ps: github網站不行(本文最初再github上編寫),會引起csp錯誤,此錯誤是用於防止內容注入攻擊的,不得不說,大網站安全措施作得就是好,轉戰segmentfault作實踐。
cors(跨域資源共享 Cross-origin resource sharing),它容許瀏覽器向跨域服務器發出XMLHttpRequest請求,從而克服跨域問題,它須要瀏覽器和服務器的同時支持。node
cors 分爲兩種請求,簡單請求和非簡單請求,關於cors的更詳細介紹,推薦阮一峯老師的 跨域資源共享 CORS 詳解,本文注重實踐。
正如上方的例子即是一個簡單請求git
var url = 'http://127.0.0.1:8888/'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.send();
如何解決此案例的跨域問題呢?
瀏覽器端,瀏覽器會自動在請求頭中添加 origin 字段,咱們不須要操做。github
Request Headers: Origin: https://github.com
服務端,Access-Control-Allow-Origin屬性,咱們須要服務端設置此屬性,指定容許的請求源域名,能夠經過指定爲 *
來指定因此域名。後端動起來:json
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/');
重啓服務,再嘗試segmentfault
此次沒有再報錯了,咱們看看服務器放回了什麼
nice!跨域成功!後端
一樣咱們在控制檯輸入一下代碼進行put(非簡單請求)
var url = 'http://127.0.0.1:8888/'; var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.send();
毫無心外的報錯
在進行非簡單請求的時候,瀏覽器會先發送一次OPTION請求來「預檢」(preflight)該請求是否被容許,請求頭中會經過Access-Control-Request-Method
,Access-Control-Request-Headers
來告訴服務器我須要用到的方法和字段,服務器經過返回的頭部信息中的Access-Control-Allow-Origin
,Access-Control-Allow-Method
來告訴瀏覽器該跨域請求是否被容許。修改後端代碼:
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/');
能夠看到瀏覽器會先發送一個預檢
當確認容許跨域以後,之後再發送該請求,就會省去預檢處理,之間看成簡單請求來操做。很明顯,修改了後端代碼後,此次的put請求時成功的。這裏就不繼續上圖了。
cors(跨域資源共享 Cross-origin resource sharing),它容許瀏覽器向跨域服務器發出XMLHttpRequest請求,從而克服跨域問題,它須要瀏覽器和服務器的同時支持。
Access-Control-Allow-Methods
,Access-Control-Allow-Headers
,Access-Control-Allow-Origin
等字段,指定容許的方法,頭部,源等信息。jsonp的原理就是利用就是利用script
標籤沒有跨域限制,能夠經過script
標籤的src屬性發送GET
請求。咱們繼續嘗試,先把後端有關跨域的設置去掉,並重啓服務
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/');
打開咱們的控制檯輸入一下代碼,利用script標籤進行jsonp請求
var script = document.createElement('script'); script.type = 'text/javascript'; script.src = `http://127.0.0.1:8888/`; document.head.appendChild(script);
能夠看到,後端正常的返回了
request success !!!
並且該請求爲GET
請求
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
可是咱們如今只是成功發送了一個跨域請求,可是咱們不像XMLHttpRequest那樣能夠在res.responseText中拿到數據,經過jsonp咱們該怎麼拿到請求的數據呢?方法就是先後端約定一個callback字段名,來傳遞函數名,前端經過該函數來拿到數據。前端代碼修改成:
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)); // 請求完後刪除添加到頁面上的script標籤 var head = document.head head.removeChild(script) }
經過callback字段來傳遞函數名onBack,後端代碼修改成
var http = require('http') var urlTool = require('url') // json 數據 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/');
重啓後端服務,而且在控制檯輸入代碼,能夠看到結果:
咱們拿到了數據,而且經過onBack函數將他輸出到了控制檯上!
script
標籤沒有跨域限制的特色,經過script
標籤的的src屬性發送GET
請求。同源策略:同源策略限制了一個源(origin)中加載文本或腳本與來自其它源(origin)中資源的交互方式,這是一個用於隔離潛在惡意文件的重要安全機制。若是兩個頁面擁有 相同 的 協議(protocol),端口(若是指定),和 主機,那麼這兩個頁面就屬於同一個源(origin)。