1. 什么是跨域?

跨域(Cross-Origin)是指浏览器出于安全考虑,限制不同源(协议、域名、端口)之间的资源交互。
同源策略(Same-Origin Policy) 要求以下三者必须一致:
2. 跨域的表现形式
当以下场景发生在不同源时,浏览器会拦截请求:
3. 常见跨域解决方案
3.1 CORS(跨域资源共享)
原理:服务端通过响应头声明允许的跨域请求来源。
实现步骤:
1.简单请求(GET/POST/HEAD,Content-Type 为 text/plain
、multipart/form-data
、application/x-www-form-urlencoded
):
服务端返回 Access-Control-Allow-Origin: *
或具体域名。
2.预检请求(复杂请求如 PUT/DELETE 或自定义头):
浏览器先发送 OPTIONS
请求,服务端需响应:
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); // 快速返回预检请求响应
}
next();
});
3.2 JSONP(JSON with Padding)
原理:利用 <script>
标签无跨域限制的特性,通过回调函数获取数据。
缺点:仅支持 GET 请求,存在安全风险(如 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);
// 服务端返回
handleResponse({ "status": "success", "data": [...] });
3.3 代理服务器
原理:通过同源的后端服务转发请求,绕过浏览器限制。
实现方式:
location /api/ {
proxy_pass https://api.example.com/;
proxy_set_header Host $host;
}
开发环境代理(如 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 协议不受同源策略限制。
示例代码:
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>
与父页面):
// 发送方
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. 调试与注意事项
// 前端
fetch(url, { credentials: 'include' });
// 服务端
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Origin", "https://your-client.com"); // 不能为通配符 *
5. 总结
推荐方案:优先使用 CORS 或代理服务器。
兼容性场景:JSONP 适用于老旧系统。
实时通信:WebSocket 是理想选择。
通过理解跨域机制及解决方案,开发者可灵活应对不同场景的跨域需求。
该文章在 2025/2/20 16:59:28 编辑过