摘要:此時(shí)完成的跨域代理配置僅僅是在開(kāi)發(fā)環(huán)境下生效,到了生產(chǎn)環(huán)境下如果是放到服務(wù)器上則還需要借助的反向代理來(lái)進(jìn)行跨域的代理。
跨域 指的是瀏覽器不能執(zhí)行其他網(wǎng)站的腳本,它是由瀏覽器的同源策略造成的,是瀏覽器對(duì) JavaScript 施加的安全限制。
同源就是指 域名,協(xié)議,端口 均相同。兩個(gè)網(wǎng)域若 域名、協(xié)議、端口 任一不同則二者的通信就出現(xiàn)了跨域問(wèn)題,前端的跨域問(wèn)題普通存在于兩個(gè)階段,一個(gè)是開(kāi)發(fā)環(huán)境調(diào)試階段,另一個(gè)發(fā)布上線后的生產(chǎn)環(huán)境運(yùn)行階段,一般生產(chǎn)環(huán)境下的跨域問(wèn)題會(huì)由運(yùn)維或?qū)嵤┤藛T來(lái)解決,但是開(kāi)發(fā)環(huán)境下的跨域問(wèn)題需要前端或后端進(jìn)行處理。
常見(jiàn)的跨域解決方案
1.jsonp 跨域
jsonp 是數(shù)據(jù)格式 JSON 的一種“使用模式”,可以讓網(wǎng)頁(yè)從別的網(wǎng)站索要數(shù)據(jù),jsonp 的原理就是利用 <script> 標(biāo)簽沒(méi)有跨域限制,通過(guò) <script> 標(biāo)簽 src 屬性,發(fā)送帶有 callback 參數(shù)的 GET 請(qǐng)求,服務(wù)端將接口返回?cái)?shù)據(jù)拼湊到 callback 函數(shù)中,返回給瀏覽器,瀏覽器解析執(zhí)行,從而前端拿到 callback 函數(shù)返回的數(shù)據(jù)。
注:用 JSONP 抓到的數(shù)據(jù)并不是 JSON,而是任意的 JavaScript ,用 JavaScript 解釋器運(yùn)行而不是用 JSON 解析器解析。所以通過(guò) Chrome 查看所有 JSONP 發(fā)送的 Get 請(qǐng)求都是 js 類(lèi)型,而非 XHR 。
下面演示下使用原生 JS 和 Ajax 實(shí)現(xiàn) jsonp 跨域的寫(xiě)法:
①原生 JS 寫(xiě)法:
<script>
// 回調(diào)執(zhí)行函數(shù)
function handleCallback(res) {
console.log(res); // {user: 'admin', callback: 'handleCallback'}
}
</script>
<script type="text/javascript" src="http://127.0.0.1:8080/login?user=admin&callback=handleCallback"></script>
②Ajax 寫(xiě)法:
$.ajax({
// 需要跨域獲取數(shù)據(jù)的網(wǎng)站 URL
url: 'http://127.0.0.1:8080/login?user=admin',
// 請(qǐng)求類(lèi)型,JSONP 只支持 GET 請(qǐng)求,可以不寫(xiě),默認(rèn)也是 GET 類(lèi)型
method: 'GET',
// 使用 $.ajax() 發(fā)起 JSONP 請(qǐng)求,必須指定 dataType: 'jsonp'
dataType: 'JSONP',
// jsonpCallback 用于設(shè)置回調(diào)函數(shù)的函數(shù)名稱(chēng)
jsonpCallback: 'handleCallback',
// success 用于接收請(qǐng)求成功后的返回值
success: function (res) {
console.log(res);
}
})
應(yīng)用場(chǎng)景:有些第三方數(shù)據(jù)接口可能會(huì)使用 jsonp 解決跨域,在實(shí)際工作中并不怎么用這種方式解決跨域問(wèn)題。主要是因?yàn)?jsonp 只支持 GET 請(qǐng)求,請(qǐng)求方式單一不能滿足開(kāi)發(fā)需求,這也是 jsonp 的致命缺點(diǎn)。
2.中間服務(wù)器代理
注:跨域問(wèn)題只存在于瀏覽器中,服務(wù)器端沒(méi)有跨域的概念。中間服務(wù)器代理的思路就是我們前端可以不跨域的去訪問(wèn)一個(gè)中間服務(wù)器(這個(gè)中間服務(wù)器和我們前端網(wǎng)域的 域名、協(xié)議、端口都相同,則不跨域),再讓中間服務(wù)器去替我們?cè)L問(wèn)這個(gè)我們本來(lái)需要跨域訪問(wèn)的網(wǎng)站,中間服務(wù)器拿到我們需要的資源然后再返還給我們即可。
這主要是一種解決跨域的思路,下面我們會(huì)介紹到在 Vue 項(xiàng)目中配置 反向代理 來(lái)解決跨域問(wèn)題時(shí)其實(shí)就是使用的這種中間服務(wù)器代理的思路。
3.CORS 跨域資源共享
CORS 是一個(gè) W3C 標(biāo)準(zhǔn),全稱(chēng)是"跨域資源共享"。它允許瀏覽器向跨源服務(wù)器,發(fā)出 XMLHttpRequest 請(qǐng)求,從而克服了 AJAX 只能同源使用的限制。
CORS 需要瀏覽器和服務(wù)器同時(shí)支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。
瀏覽器將 CORS 請(qǐng)求分為簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求。對(duì)于簡(jiǎn)單請(qǐng)求,瀏覽器直接發(fā)出 CORS 請(qǐng)求,具體來(lái)說(shuō)就是在頭信息中,增加一個(gè) Origin 字段。服務(wù)器會(huì)根據(jù)這個(gè)字段決定是否同意此次請(qǐng)求。而非簡(jiǎn)單請(qǐng)求就是對(duì)服務(wù)器有特殊要求的請(qǐng)求,比如 PUT 請(qǐng)求、DELETE 請(qǐng)求等,非簡(jiǎn)單請(qǐng)求的 CORS 請(qǐng)求,會(huì)在正式通信之前,增加一次 HTTP 查詢(xún)請(qǐng)求,稱(chēng)為“預(yù)檢請(qǐng)求”(preflight),預(yù)檢請(qǐng)求的請(qǐng)求類(lèi)型是 OPTIONS 表示詢(xún)問(wèn),服務(wù)器會(huì)先對(duì)預(yù)檢請(qǐng)求進(jìn)行回應(yīng),如果允許了此次的跨域才會(huì)發(fā)起正式的非簡(jiǎn)單請(qǐng)求,所以非簡(jiǎn)單請(qǐng)求實(shí)際上會(huì)有兩次請(qǐng)求記錄(一次預(yù)檢請(qǐng)求一次正式請(qǐng)求)。
簡(jiǎn)單來(lái)說(shuō)實(shí)現(xiàn) CORS 跨域資源共享其實(shí)就是在發(fā)起請(qǐng)求前或在服務(wù)器端進(jìn)行請(qǐng)求頭、請(qǐng)求類(lèi)型等配置,符合配置項(xiàng)條件的請(qǐng)求就可以正常與該服務(wù)器進(jìn)行通信。
簡(jiǎn)單請(qǐng)求中重要配置字段如下:
Access-Control-Allow-Origin 是必須的配置項(xiàng),它的值要么是請(qǐng)求時(shí) Origin 字段的值(包含:協(xié)議、域名、端口),要么是一個(gè) * ,表示接受任意域名的請(qǐng)求。
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials 該字段可選。它的值是一個(gè)布爾值,表示是否允許發(fā)送 Cookie 。默認(rèn)情況下,Cookie不包括在CORS請(qǐng)求之中。設(shè)為 true ,即表示服務(wù)器明確許可,Cookie 可以包含在請(qǐng)求中,一起發(fā)給服務(wù)器。這個(gè)值也只能設(shè)為 true ,如果服務(wù)器不要瀏覽器發(fā)送 Cookie ,刪除該字段即可。
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers 該字段可選。CORS請(qǐng)求時(shí),XMLHttpRequest 對(duì)象的getResponseHeade() 方法只能拿到6個(gè)基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在 Access-Control-Expose-Headers 里面指定。
Access-Control-Expose-Headers: FooBar
非簡(jiǎn)單請(qǐng)求的配置:
非簡(jiǎn)單請(qǐng)求除了需要配置 Origin 字段外,一般還需要配置如下字段:
Access-Control-Allow-Methods 該字段是必須的,用來(lái)列出瀏覽器的 CORS 請(qǐng)求會(huì)用到哪些HTTP方法。如 PUT 、DELETE 等
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Request-Headers 該字段是一個(gè)逗號(hào)分隔的字符串,指定瀏覽器CORS請(qǐng)求會(huì)額外發(fā)送的頭信息字段。
Access-Control-Request-Headers: X-Custom-Header
CORS 跨域資源共享可以在前端或后端進(jìn)行配置,是目前常用的解決瀏覽器跨域的方案,較之 jsonp 其更加強(qiáng)大,幾乎支持所有的請(qǐng)求類(lèi)型。
4.配置反向代理實(shí)現(xiàn)跨域的方法
配置反向代理 是前端自行在項(xiàng)目中進(jìn)行配置來(lái)解決跨域的一種方式,主要就是在項(xiàng)目中設(shè)置代理,開(kāi)啟代理就會(huì)在本地創(chuàng)建一個(gè)虛擬服務(wù)器,我們會(huì)通過(guò)它來(lái)發(fā)送請(qǐng)求,它也會(huì)把請(qǐng)求返回的數(shù)據(jù)返還給我們。主要就是使用中間服務(wù)器代理的思路。
在 Vue 項(xiàng)目中配置反向代理:(分為 CLI 2.X 和 CLI 3.X 搭建的項(xiàng)目)
CLI 2.X 搭建的項(xiàng)目配置路徑:打開(kāi)項(xiàng)目的 config/index.js 文件,找到 dev 中的 proxyTable: {}, 字段,(如果沒(méi)有就添加一個(gè)),將該字段進(jìn)行如下配置:
// 設(shè)置代理
proxyTable: {
// 需要代理的接口,當(dāng)?shù)刂分杏?/api 時(shí)就會(huì)觸發(fā)代理機(jī)制
'/api': {
target: 'http://39.97.33.178', // 目標(biāo)服務(wù)器域名
ws: true, // 是否啟用 websockets,就開(kāi)啟即可
changeOrigin: true, // 是否跨域,需要設(shè)置此值為 true 才可以讓本地服務(wù)器代理我們發(fā)出請(qǐng)求
pathRewrite: { // 路徑重寫(xiě)
'^/api': '' //重定向,即服務(wù)器端是否需要將匹配到的值替換成其他值來(lái)進(jìn)行數(shù)據(jù)請(qǐng)求,假設(shè)我們想把 localhost:8888/api/login 變成 http://39.97.33.178/login 就需要這么做
}
}
},
CLI 3.X 搭建的項(xiàng)目默認(rèn)的配置文件是隱藏的,需要手動(dòng)在根目錄創(chuàng)建一個(gè) vue.config.js 文件,在該文件中 進(jìn)行如下配置:
// 設(shè)置代理
modele.exports = {
devServer: {
// 設(shè)置代理
proxy: {
// 需要代理的接口,當(dāng)?shù)刂分杏?/api 時(shí)就會(huì)觸發(fā)代理機(jī)制
'/api': {
target: 'http://39.97.33.178', // 目標(biāo)服務(wù)器域名
ws: true, // 是否啟用 websockets,就開(kāi)啟即可
changeOrigin: true, // 是否跨域,需要設(shè)置此值為 true 才可以讓本地服務(wù)器代理我們發(fā)出請(qǐng)求
pathRewrite: {
'^/api': '' // 重定向,即服務(wù)器端是否需要將匹配到的值替換成其他值來(lái)進(jìn)行數(shù)據(jù)請(qǐng)求,假設(shè)我們想把 localhost:8888/api/login 變成 http://39.97.33.178/login 就需要這么做
}
}
},
}
}
注意:vue.config.js 的改動(dòng)如果需要生效,需要進(jìn)行重啟服務(wù)。
此時(shí)完成的跨域代理配置僅僅是在開(kāi)發(fā)環(huán)境下生效,到了生產(chǎn)環(huán)境下如果是放到 Nginx 服務(wù)器上則還需要借助 Nginx 的反向代理來(lái)進(jìn)行跨域的代理。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/989.html
摘要:同源策略瀏覽器的一個(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è)面具有相...
摘要:同源策略做了很?chē)?yán)格的限制,但是在實(shí)際的場(chǎng)景中,又確實(shí)有很多地方需要突破同源策略的限制,也就是我們常說(shuō)的跨域。使用跨域由于同源策略,一般來(lái)說(shuō)位于的網(wǎng)頁(yè)無(wú)法與不是的服務(wù)器溝通,而的元素是一個(gè)例外。 本菜雞最近在寫(xiě)某個(gè)頁(yè)面請(qǐng)求數(shù)據(jù)時(shí),報(bào)了如下的錯(cuò)誤。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...
摘要:同源策略做了很?chē)?yán)格的限制,但是在實(shí)際的場(chǎng)景中,又確實(shí)有很多地方需要突破同源策略的限制,也就是我們常說(shuō)的跨域。使用跨域由于同源策略,一般來(lái)說(shuō)位于的網(wǎng)頁(yè)無(wú)法與不是的服務(wù)器溝通,而的元素是一個(gè)例外。 本菜雞最近在寫(xiě)某個(gè)頁(yè)面請(qǐng)求數(shù)據(jù)時(shí),報(bào)了如下的錯(cuò)誤。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...
摘要:同源策略做了很?chē)?yán)格的限制,但是在實(shí)際的場(chǎng)景中,又確實(shí)有很多地方需要突破同源策略的限制,也就是我們常說(shuō)的跨域。使用跨域由于同源策略,一般來(lái)說(shuō)位于的網(wǎng)頁(yè)無(wú)法與不是的服務(wù)器溝通,而的元素是一個(gè)例外。 本菜雞最近在寫(xiě)某個(gè)頁(yè)面請(qǐng)求數(shù)據(jù)時(shí),報(bào)了如下的錯(cuò)誤。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...
閱讀 735·2023-04-25 19:43
閱讀 3981·2021-11-30 14:52
閱讀 3807·2021-11-30 14:52
閱讀 3871·2021-11-29 11:00
閱讀 3802·2021-11-29 11:00
閱讀 3904·2021-11-29 11:00
閱讀 3580·2021-11-29 11:00
閱讀 6182·2021-11-29 11:00