1. 什么是跨域?

跨域(Cross-Origin)是指瀏覽器出于安全考慮,限制不同源(協(xié)議、域名、端口)之間的資源交互。
同源策略(Same-Origin Policy) 要求以下三者必須一致:
2. 跨域的表現(xiàn)形式
當(dāng)以下場景發(fā)生在不同源時(shí),瀏覽器會攔截請求:
3. 常見跨域解決方案
3.1 CORS(跨域資源共享)
原理:服務(wù)端通過響應(yīng)頭聲明允許的跨域請求來源。
實(shí)現(xiàn)步驟:
1.簡單請求(GET/POST/HEAD,Content-Type 為 text/plain、multipart/form-data、application/x-www-form-urlencoded):
服務(wù)端返回 Access-Control-Allow-Origin: * 或具體域名。
2.預(yù)檢請求(復(fù)雜請求如 PUT/DELETE 或自定義頭):
瀏覽器先發(fā)送 OPTIONS 請求,服務(wù)端需響應(yīng):
Access-Control-Allow-Origin: https://your-domain.comAccess-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: Content-Type, Authorization
示例代碼(Node.js Express):
app.use((req, res, next) => { res.header("Access-Control-Allow-Origin", "https://your-client.com"); res.header("Access-Control-Allow-Headers", "Content-Type, Authorization"); res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); if (req.method === "OPTIONS") { return res.sendStatus(200); // 快速返回預(yù)檢請求響應(yīng) } next();});
3.2 JSONP(JSON with Padding)
原理:利用 <script> 標(biāo)簽無跨域限制的特性,通過回調(diào)函數(shù)獲取數(shù)據(jù)。
缺點(diǎn):僅支持 GET 請求,存在安全風(fēng)險(xiǎn)(如 XSS)。
示例代碼:
// 前端function handleResponse(data) { console.log("Received:", data);}const script = document.createElement('script');script.src = 'https://api.example.com/data?callback=handleResponse';document.body.appendChild(script);
// 服務(wù)端返回handleResponse({ "status": "success", "data": [...] });
3.3 代理服務(wù)器
原理:通過同源的后端服務(wù)轉(zhuǎn)發(fā)請求,繞過瀏覽器限制。
實(shí)現(xiàn)方式:
location /api/ { proxy_pass https://api.example.com/; proxy_set_header Host $host;}
開發(fā)環(huán)境代理(如 webpack-dev-server)
// vue.config.js / webpack.config.jsmodule.exports = { devServer: { proxy: { '/api': { target: 'https://api.example.com', changeOrigin: true, } } }};
3.4 WebSocket
原理:WebSocket 協(xié)議不受同源策略限制。
?示例代碼:
const socket = new WebSocket('wss://api.example.com/socket');socket.onmessage = (event) => { console.log('Message:', event.data);};
3.5 其他方案
document.domain = "example.com";
postMessage API
用于窗口間通信(如 <iframe> 與父頁面):
// 發(fā)送方window.parent.postMessage('Hello', 'https://parent-domain.com');
// 接收方window.addEventListener('message', (event) => { if (event.origin !== 'https://child-domain.com') return; console.log('Received:', event.data);});
4. 調(diào)試與注意事項(xiàng)
// 前端fetch(url, { credentials: 'include' });
// 服務(wù)端res.header("Access-Control-Allow-Credentials", "true");res.header("Access-Control-Allow-Origin", "https://your-client.com"); // 不能為通配符 *
?
5. 總結(jié)
推薦方案:優(yōu)先使用 CORS 或代理服務(wù)器。
兼容性場景:JSONP 適用于老舊系統(tǒng)。
實(shí)時(shí)通信:WebSocket 是理想選擇。
通過理解跨域機(jī)制及解決方案,開發(fā)者可靈活應(yīng)對不同場景的跨域需求。
該文章在 2025/2/20 16:59:28 編輯過