关于跨域
在使用Vue搭建的一個后端管理系統(tǒng)中,我使用axios請求本地的Node環(huán)境下的接口,但是請求失敗,然后我錯誤信息是:
大概意思就是不能訪問http://localhost:8080 我的Vue項目端口是http://localhost:8081,Node服務端運行在http://localhost:8080端口上,也就是說因為請求端口和響應端口不一致,所以請求失敗。 我也在網(wǎng)上查看了一些關于跨域出現(xiàn)的原因及解決的方法,并記錄下來。為什么會有跨域
跨域一句話的理解就是:服務端和請求端的地址不一樣。
什么是跨域
Ajax 的便利性大家都清楚,可以在不向服務器提交完整的頁面的情況下,實現(xiàn)局部更新頁面。但是瀏覽器處于對安全方面的考慮,不允許跨域調(diào)用其他頁面的對象。
其實這個也不能怪瀏覽器,假設誰都可以隨隨便便向你發(fā)送請求,那樣有很大的安全隱患。
根據(jù)瀏覽器的同源策略, 只有當協(xié)議,域名,端口相同的時候才算是同源, 反之則均視為是一個跨域的請求.
也就是說我剛剛的Vue端口是8081,服務端端口是8080,端口不一樣,因為同源策略的存在 ,所有我的請求會失敗。
一個問題,當找到了原因,這個問題就解決了一半了。
怎么解決跨域
下面就先介紹三種跨全域的方法:
JSONP
應該是最常見解決跨域的方法了, 他為什么能解決跨域呢,是因為Web 頁面上調(diào)用 js 文件不受瀏覽器同源策略的影響,所以通過 Script 便簽可以進行跨域的請求:
然后使用node server.js運行 前端:
//index.html <body><script>function jsonpCallback(data) {console.log('獲得 X 數(shù)據(jù):' + data.x);}</script><script src="http://localhost:3000?callback=jsonpCallback"></script> </body> 復制代碼之后打開index.html;就可以在控制臺看到返回的數(shù)據(jù)了:
至此,通過 JSONP 跨域獲取數(shù)據(jù)已經(jīng)成功了,jsonp這種方法跨域,他的兼容性很好,可以在古老的瀏覽器中國使用,因為這種方法是利用了<script>標簽的特殊性,所有只支持GET請求。
CORS
CORS 是一個 W3C 標準,全稱是"跨域資源共享"(Cross-origin resource sharing)它允許瀏覽器向跨源服務器,發(fā)出 XMLHttpRequest 請求,從而克服了 ajax 只能同源使用的限制。
CORS 需要瀏覽器和服務器同時支持才可以生效,對于開發(fā)者來說,CORS 通信與同源的 ajax 通信沒有差別,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn) ajax 請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。
因此,實現(xiàn) CORS 通信的關鍵是服務器。只要服務器實現(xiàn)了 CORS 接口,就可以跨源通信。
前端:
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> <script> $.ajax({url:"http://127.0.0.1:3000",success:function(res){var res = JSON.parse(res);$('body').text(res.data);console.log(res.data);} }); </script> 復制代碼這次前端啟動需要使用node-server來啟動,使用npm install node-server下載,然后當前目錄下使用node-server就可以了 后端:
const http = require('http');http.createServer((req, res)=>{ const data = {'data': 'Hello world'//返回的數(shù)據(jù) }; res.writeHead(200, {'Access-Control-Allow-Origin': 'http://127.0.0.1:8080'}); //設置的頭部信息需要和前端請求的地址一致 res.end(JSON.stringify(data)); //返回data }).listen(3000, '127.0.0.1');console.log('啟動服務,監(jiān)聽 127.0.0.1:3000'); 復制代碼使用命令node server.js啟動;
CORS與JSONP的使用目的相同,但是比JSONP更強大。
JSONP只支持GET請求,CORS支持所有類型的HTTP請求。JSONP的優(yōu)勢在于支持老式瀏覽器,以及可以向不支持CORS的網(wǎng)站請求數(shù)據(jù)。
Server Proxy
服務器代理,顧名思義,當你需要有跨域的請求操作時發(fā)送請求給后端,讓后端幫你代為請求,然后最后將獲取的結果發(fā)送給你。
假設有這樣的一個場景,你的頁面需要獲取?CNode:Node.js專業(yè)中文社區(qū)?論壇上一些數(shù)據(jù),如通過?cnodejs.org/api/v1/topi…,當時因為不同域,所以你可以將請求后端,讓其對該請求代為轉(zhuǎn)發(fā)。
后端代碼如下:
const url = require('url'); const http = require('http'); const https = require('https');http.createServer((req, res)=>{ const path = url.parse(req.url).path.slice(1); //核對請求路由是否一致 if(path === 'topics'){https.get('https://cnodejs.org/api/v1/topics', (resp)=>{//https代發(fā)請求let data='';resp.on('data', chunk=>{data+= chunk});resp.on('end', ()=>{res.writeHead(200,{'Content-Type': 'application/json; charset=utf-8'});res.end(data);//返回數(shù)據(jù)})}) }}).listen(3000, '127.0.0.1');console.log('啟動服務,監(jiān)聽 127.0.0.1:3000'); 復制代碼前端代碼:
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> <script> $.ajax({url:"https://cnodejs.org/api/v1/topics",success:function(res){$('body').text(JSON.stringify(res));console.log(res);} }); </script> 復制代碼這樣就成功了
總結
常用的跨域方式基本就是這三種:
其他的跨域方式還有:location.hash、window.name、postMessage等方式,有時間也可以了解一下。
參考資料:
- 跨域資源共享 CORS 詳解[阮一峰的博客]:www.ruanyifeng.com/blog/2016/0…
- 關于跨域,你想知道的全在這里:zhuanlan.zhihu.com/p/25778815
- 不要再問我跨域的問題了[sf]:segmentfault.com/a/119000001…
- 關于跨域,以及跨域的幾種方式[cnblog]:www.cnblogs.com/chenshishuo…
- 瀏覽器的同源策略[MDN]:developer.mozilla.org/zh-CN/docs/…
轉(zhuǎn)載于:https://juejin.im/post/5c8b67f6f265da2dd2191308
總結
- 上一篇: 十分钟熟练Dockerfile指令
- 下一篇: PHP SHA1withRSA加密生成签