1. 什么是跨域?

跨域(Cross-Origin)是指瀏覽器出于安全考慮,限制不同源(協(xié)議、域名、端口)之間的資源交互。
同源策略(Same-Origin Policy) 要求以下三者必須一致:
2. 跨域的表現(xiàn)形式
當(dāng)以下場景發(fā)生在不同源時,瀏覽器會攔截請求:
3. 常見跨域解決方案
3.1 CORS(跨域資源共享)
原理:服務(wù)端通過響應(yīng)頭聲明允許的跨域請求來源。
實現(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.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-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ù)。
缺點:僅支持 GET 請求,存在安全風(fēng)險(如 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ā)請求,繞過瀏覽器限制。
實現(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.js
module.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)試與注意事項
// 前端
fetch(url, { credentials: 'include' });
// 服務(wù)端
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Origin", "https://your-client.com"); // 不能為通配符 *
?
5. 總結(jié)
通過理解跨域機制及解決方案,開發(fā)者可靈活應(yīng)對不同場景的跨域需求。
該文章在 2025/2/20 16:59:28 編輯過