前端JS經(jīng)典問題之跨域的解決方案
一、概念
1. 瀏覽器的同源策略
瀏覽器為確保資源的安全,而遵循的一種策略。
2. 源
源 = 協(xié)議 + 域名 + 端口
3. 同源和非同源
當(dāng)兩個(gè)源只有他們的協(xié)議、域名、端口都一致,才是同源,否則是非同源。
4. 同源請(qǐng)求和非同源請(qǐng)求
如果是同源發(fā)出的請(qǐng)求就是同源請(qǐng)求,如果是非同源發(fā)出的請(qǐng)求就是非同源請(qǐng)求。
5. 跨域
[所處源] 與 [目標(biāo)源] 不一致,就會(huì)導(dǎo)致跨域。
二、瀏覽器會(huì)對(duì)跨域做哪些限制
[源 A] 和 [源 B]是非同源的,則瀏覽器會(huì)有以下限制。
1. DOM 訪問限制
[源 A]的腳本不能讀取和操作[源 B]的 DOM
2. Cookie 訪問限制
[源 A]不能訪問[源 B]的 Cookie
3. Ajax 響應(yīng)數(shù)據(jù)限制
[源 A]可以給[源 B]發(fā)請(qǐng)求,但無法獲取[源 B]的返回的數(shù)據(jù)
三、注意點(diǎn)
跨域限制僅存在瀏覽器端,服務(wù)端不存在跨域限制
即時(shí)跨域了,Ajax 請(qǐng)求也可以正常發(fā)出,但響應(yīng)數(shù)據(jù)不會(huì)交給開發(fā)者。
<link>、<script>、<img>...這些標(biāo)簽發(fā)出的請(qǐng)求也可能跨域,只不過瀏覽器對(duì)標(biāo)簽不做嚴(yán)格限制,對(duì)開發(fā)幾乎無影響。
四、CORS 解決跨域
CORS 即跨源資源共享(Cross-Origin Resource Sharing),CORS 是一種機(jī)制,它允許 Web 應(yīng)用服務(wù)器進(jìn)行跨域訪問控制,使不同源的網(wǎng)站之間能夠安全地共享資源。
在默認(rèn)情況下,出于安全考慮,瀏覽器會(huì)限制從一個(gè)源(協(xié)議、域名、端口)加載的腳本獲取或操作另一個(gè)源的資源。而 CORS 為 Web 應(yīng)用提供了一種安全的方式來繞過這種同源策略的限制。
使用 CORS 解決跨域是最正統(tǒng)的方式,且要求服務(wù)器是"自己人"
1. 簡(jiǎn)單請(qǐng)求和復(fù)雜請(qǐng)求
簡(jiǎn)單請(qǐng)求
請(qǐng)求方式:GET、HEAD、POST
Content-type:text/plain、multipart/form-data、application/x-www-form-urlencoded
請(qǐng)求頭字段符合《CORS 安全規(guī)范》,只要你改了請(qǐng)求頭就變復(fù)雜請(qǐng)求了。
復(fù)雜請(qǐng)求
不是簡(jiǎn)單請(qǐng)求就是復(fù)雜請(qǐng)求,復(fù)雜請(qǐng)求會(huì)自動(dòng)發(fā)送預(yù)檢請(qǐng)求。
2. 解決簡(jiǎn)單請(qǐng)求
以 nodeJS 為例,服務(wù)器端設(shè)置響應(yīng)頭 Access-Control-Allow-Origin,值為發(fā)送請(qǐng)求的源表示,只要從這個(gè)源發(fā)送的請(qǐng)求,都通過。值為 "\*" 表示所有不同源發(fā)來的請(qǐng)求都通過。
app.get("/xxx", (res, req) => { res.setHeader("Access-Control-Allow-Origin", "發(fā)送請(qǐng)求源" | "*"); res.send(); });
3. 解決復(fù)雜請(qǐng)求
以 nodeJS 為例,服務(wù)器設(shè)置響應(yīng)頭,與請(qǐng)求頭一一對(duì)應(yīng),使用 cors 插件。
app.use( cors({ origin: "xxx", // 允許源 methods: ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"], // 允許方法 allowedHeaders: ["xxx"], // 允許的自定義頭 exposedHeaders: ["xxx"], // 要暴露的響應(yīng)頭 }) ); app.get("/xxx", (res, req) => { res.setHeader("xxx", "xxx"); res.send(); });
五、JSONP 解決跨域
JSONP 利用<script>標(biāo)簽可以跨域加載腳本,且不受嚴(yán)格模式限制的特性。
1. 基本流程
第一步:創(chuàng)建 script 標(biāo)簽,將 src 設(shè)置為跨域請(qǐng)求的 url。同時(shí)準(zhǔn)備一個(gè)回調(diào)函數(shù),這個(gè)函數(shù)處理返回來的數(shù)據(jù)。
第二步:服務(wù)端接受到請(qǐng)求后,將數(shù)據(jù)封裝在回調(diào)函數(shù)中返回
第三步:客戶端回調(diào)函數(shù)被調(diào)用,數(shù)據(jù)以參數(shù)的形式傳入回調(diào)函數(shù)
2. 例子
服務(wù)端代碼
let list = [1, 2, 3]; app.get("/table", (req, res) => { const { callback } = req.query; res.send(`${callback}(${JSON.stringify(list)})`); });
客戶端代碼
function test(data) { console.log(data); } function getTable() { const script = document.createElement("script"); script.onload = () => { script.remove(); }; script.src = "http://xxx.xx.xx:8080/table?callback=test"; document.body.appendChild(script); }
六、配置代理解決跨域
1. 自己配置代理服務(wù)器
借助 http-proxy-middleware 配置代理
const { createProxyMiddleware } = require("http-proxy-middleware"); app.use( "/api", createProxyMiddleware({ target: "https://www.baidu.com", changeOrigin: true, pathRewrite: { "^/api": "", }, }) );
2. 使用 Nginx 搭建代理服務(wù)器
2.1 設(shè)置響應(yīng)頭
server { listen 80; server_name your_domain.com; location /api/ { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; if ($request_method = 'OPTIONS') { return 204; } proxy_pass http://your_backend_server; } }
2.2 反向代理
通過 Nginx 將跨域請(qǐng)求代理到目標(biāo)服務(wù)器,讓瀏覽器認(rèn)為是同源請(qǐng)求。
server { listen 80; server_name frontend.com; location /api/ { proxy_pass http://backend.com; } }
3. 腳手架服務(wù)器
比如 vue3 里的配置文件 vite.config.js 可以配置代理的地址
import { defineConfig } from "vite"; // https://vitejs.dev/config/ export default defineConfig(() => { return { server: { host: "127.0.0.1", port: 8081, strictPort: false, open: true, proxy: { "/dev-api": { target: "http://localhost:1112", changeOrigin: true, rewrite: (path) => path.replace(/^\/dev-api/, ""), }, }, }, }; });
總結(jié)
到此這篇關(guān)于前端JS經(jīng)典問題之跨域的解決方案的文章就介紹到這了,更多相關(guān)前端JS跨域解決方案內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序?qū)崿F(xiàn)簡(jiǎn)單秒表設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)簡(jiǎn)單秒表設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09webpack打包優(yōu)化的幾個(gè)方法總結(jié)
這篇文章主要介紹了webpack打包優(yōu)化的幾個(gè)方法總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02JavaScript 解析讀取XML文檔 實(shí)例代碼
應(yīng)項(xiàng)目之需求,需用JS操作XML文檔,遂上網(wǎng)查資料,感覺這篇文章還不錯(cuò),特轉(zhuǎn)載到此地,與大家共享!2009-07-07js合并兩個(gè)數(shù)組生成合并后的key:value數(shù)組
這篇文章主要是介紹了js將兩個(gè)數(shù)組合并為類json方式,需要的朋友可以參考下2018-05-05