如何解決跨域?常見解決方案淺析
跨領域是開發中常會遇到的場景,也是面試中常會討論的問題。掌握常見的跨域解決方案及其背後的原理,不僅可以提高我們的開發效率,還能在面試中表現的更加游刃有餘。
因此今天就來跟大家從前端的角度來聊聊解決跨域常見的幾種方式。
什麼是跨域
在講跨域之前,我們先來看看URL的組成內容:
一個URL的組成,通常包含協定、主機名稱、連接埠號碼、路徑、查詢參數和錨點幾個部分。
這裡展示了一個URL的範例:
https://www.example.com:8080/path/resource.html?page=1&sort=desc#header
在上述範例中:
● 協定為HTTPS
● 主機名為www.example.com
● 端口編號為8080
● 路徑為/path/resource.html
● 查詢參數為page=1&sort=desc
● 錨點為header
##所謂跨域,指的是請求URL中協定、主機名稱、連接埠號碼中任一個部分不相同。
以上述URL為例,以下幾種寫法都算是和它跨域:http://www.example.com:8080/ // 协议不同 https://www.example.a.com:8080/ // 主机名不同 https://www.example.com:8081/ // 端口号不同
為什麼會跨域
其實跨域問題的出現是受限於瀏覽器的同源策略。
所謂的同源策略,其實是瀏覽器的安全機制,用來限制一個網頁中網路請求僅能夠存取來自相同來源(網域名稱、協定和連接埠號碼皆相同)的資源,主要目的是防止惡意網站透過腳本竊取其他網站的敏感數據,保障使用者的隱私和安全。
如何解決跨域
前文說到,跨域問題的出現是受限於瀏覽器的同源策略,那麼常見的解決跨域問題的方案,其實也是圍繞著瀏覽器展開的:1.代理伺服器
在我們平常的開發中,解決跨域問題最常使用的方案是使用代理伺服器。
代理伺服器解決跨網域問題其實是抓住了同源策略只受限於瀏覽器存取伺服器,對於伺服器存取伺服器並沒有限制的特點,作為中間伺服器做了一個請求轉送的功能。
具體來說,就是前端工程師編寫的網頁運行在由webpack等腳手架搭建的代理伺服器上,當前端網頁在瀏覽器中發起網絡請求時,其實這個請求是發送到代理伺服器上的,然後代理伺服器會將請求轉送給目標伺服器,再將目標伺服器回傳的回應轉送給客戶端。 代理伺服器在過程中扮演了一個中轉的角色,可以對請求和回應進行一些修改、過濾和攔截,以實現一些特定的功能。因為前端網頁運行在代理伺服器上,所以不存在跨域問題。
那麼在線上環境和開發環境下,代理伺服器是如何做請求轉送的呢?1.線上環境
在線上環境下,我們一般會採用nginx來做反向代理,從而把前端的請求轉送到目標接口上。
nginx是一個輕量級高並發的web伺服器,基於事件驅動,而且跨平台,window和Linux都可以進行設定。它作為代理伺服器來解決開發中的跨域問題的主要方法就是監聽線上前端網址的運行端口,然後碰到包含特殊標記的請求後就進行請求轉發 。
2.開發環境
在開發環境下,無論是藉助於webpack還是使用vite或其他腳手架搭建的前端項目,解決跨域問題的核心是借助http-proxy-middleware中間件實現的。而http-proxy-middleware中介軟體的核心又是對http-proxy的進一步封裝。
這裡先展示一下在專案中使用http-proxy-middleware來實作請求轉送功能的範例程式碼:
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = { server: { proxy: { // 将 /api/* 的请求代理到 http://localhost:3000/* '/api': { target: 'http://localhost:3000', changeOrigin: true, pathRewrite: { '^/api': '/' } } } } };
我們可以自己使用原生node,借助http-proxy庫來建立一個具有請求轉發功能的代理伺服器Demo,有興趣的朋友可以自己測試玩玩:
1. 首先需要建立一個空資料夾(全英命名)作為專案資料夾,然後使用npm init -y指令將專案升級為node的專案:
npm init -y
2. 接著在專案根目錄下建立一個index.html檔案用於發起跨域請求:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>请求转发测试</title> </head> <body> <h1>请求转发测试</h1> <p id="message"></p> <script> fetch('/api/login') .then(response => response.text()) .then(data => { document.getElementById('message').textContent = data; }); </script> </body> </html>
3. 接著在專案根目錄下新建index .js檔案來寫服務端的程式碼。
index.js檔案是實作具有請求轉送功能的代理伺服器的核心檔案。
const http = require('http'); const httpProxy = require('http-proxy'); const fs = require('fs'); const path = require('path'); // 创建代理服务器实例 const proxy = httpProxy.createProxyServer({}); // 创建HTTP服务器 const server = http.createServer((req, res) => { if (req.url === '/' || req.url.endsWith('.html')) { // 读取HTML文件 const filename = path.join(__dirname, 'index.html'); fs.readFile(filename, 'utf8', (err, data) => { if (err) { res.writeHead(500); res.end('Error reading HTML file'); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(data); } }); } else if (req.url.startsWith('/api')) { // 重写路径,替换跨域关键词 req.url = req.url.replace(/^\/api/, ''); // 将请求转发至目标服务器 proxy.web(req, res, { target: 'http://localhost:3000/', changeOrigin: true, }); } }); // 监听端口 server.listen(8080, () => { console.log('Server started on port 8080'); });
4. 接著編寫目標伺服器target.js檔案的內容,用於測試跨網域存取:
const http = require('http'); const server = http.createServer((req, res) => { if (req.url.startsWith('/login')) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('我是localhost主机3000端口下的方法,恭喜你访问成功!'); } else { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello, world!'); } }); server.listen(3000, () => { console.log('Target server is listening on port:3000'); })
5. 打开终端,输入启动目标服务器的命令:
node ./target.js //项目根目录下执行
6. 再开一个终端启动代理服务器,等待浏览器端发起请求就可以啦:
node ./index.js //项目根目录下执行
7. 最后在浏览器里访问http://localhost:8080, 打开控制台即可查看效果:
可以发现,浏览器network模块的网络请求确实是访问的8080端口的方法,但是我们的服务器默默的做了请求转发的功能,并将请求转发获取到的内容返回到了前端页面上。
其实http-proxy是对node内置库http的进一步封装,网络请求的核心部分还是使用http创建一个服务器对象去访问的。感兴趣的同学可以再读读http-proxy的源码~
除了代理服务器这种绕过浏览器同源策略的解决方式外,从前端的角度解决跨域问题还有如下一些常见的方法:
1.借助JSONP
JSONP的原理是通过动态创建
人工智慧驅動的應用程序,用於創建逼真的裸體照片 用於從照片中去除衣服的線上人工智慧工具。 免費脫衣圖片 AI脫衣器 免費產生 AI 無盡。 好用且免費的程式碼編輯器 中文版,非常好用 強大的PHP整合開發環境 視覺化網頁開發工具 神級程式碼編輯軟體(SublimeText3)
熱AI工具
Undresser.AI Undress
AI Clothes Remover
Undress AI Tool
Clothoff.io
AI Hentai Generator
熱門文章
熱工具
記事本++7.3.1
SublimeText3漢化版
禪工作室 13.0.1
Dreamweaver CS6
SublimeText3 Mac版
熱門話題

確認 Nginx 是否啟動的方法:1. 使用命令行:systemctl status nginx(Linux/Unix)、netstat -ano | findstr 80(Windows);2. 檢查端口 80 是否開放;3. 查看系統日誌中 Nginx 啟動消息;4. 使用第三方工具,如 Nagios、Zabbix、Icinga。

在 Linux 中啟動 Nginx 的步驟:檢查 Nginx 是否已安裝。使用 systemctl start nginx 啟動 Nginx 服務。使用 systemctl enable nginx 啟用在系統啟動時自動啟動 Nginx。使用 systemctl status nginx 驗證啟動是否成功。在 Web 瀏覽器中訪問 http://localhost 查看默認歡迎頁面。

在雲服務器上配置 Nginx 域名的方法:創建 A 記錄,指向雲服務器的公共 IP 地址。在 Nginx 配置文件中添加虛擬主機塊,指定偵聽端口、域名和網站根目錄。重啟 Nginx 以應用更改。訪問域名測試配置。其他注意事項:安裝 SSL 證書啟用 HTTPS、確保防火牆允許 80 端口流量、等待 DNS 解析生效。

啟動 Nginx 服務器需要按照不同操作系統採取不同的步驟:Linux/Unix 系統:安裝 Nginx 軟件包(例如使用 apt-get 或 yum)。使用 systemctl 啟動 Nginx 服務(例如 sudo systemctl start nginx)。 Windows 系統:下載並安裝 Windows 二進製文件。使用 nginx.exe 可執行文件啟動 Nginx(例如 nginx.exe -c conf\nginx.conf)。無論使用哪種操作系統,您都可以通過訪問服務器 IP

在 Linux 中,使用以下命令檢查 Nginx 是否已啟動:systemctl status nginx根據命令輸出進行判斷:如果顯示 "Active: active (running)",則 Nginx 已啟動。如果顯示 "Active: inactive (dead)",則 Nginx 已停止。

如何在 Windows 中配置 Nginx?安裝 Nginx 並創建虛擬主機配置。修改主配置文件並包含虛擬主機配置。啟動或重新加載 Nginx。測試配置並查看網站。選擇性啟用 SSL 並配置 SSL 證書。選擇性設置防火牆允許 80 和 443 端口流量。

如何解決 Nginx 403 Forbidden 錯誤?檢查文件或目錄權限;2. 檢查 .htaccess 文件;3. 檢查 Nginx 配置文件;4. 重啟 Nginx。其他可能原因還包括防火牆規則、SELinux 設置或應用程序問題。

解決 Nginx 跨域問題有兩種方法:修改跨域響應頭:添加指令以允許跨域請求,指定允許的方法和頭,以及設置緩存時間。使用 CORS 模塊:啟用模塊並配置 CORS 規則,允許跨域請求、方法、頭和設置緩存時間。
