跨域访问的原理与限制
跨域问题源于浏览器的同源策略(Same-Origin Policy),该策略限制不同源(协议、域名、端口)之间的资源交互。同源策略是浏览器的重要安全机制,但现代开发中常需合法跨域通信。
JSONP实现跨域
JSONP利用<script>标签不受同源策略限制的特性实现跨域。客户端动态创建<script>标签,服务端返回包裹在回调函数中的JSON数据。
// 客户端实现
function handleResponse(data) {
console.log('Received:', data);
}
const script = document.createElement('script');
script.src = 'http://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);
// 服务端响应示例(Node.js)
app.get('/data', (req, res) => {
const data = { userId: 123, name: 'John' };
const callback = req.query.callback;
res.send(`${callback}(${JSON.stringify(data)})`);
});
CORS机制详解
跨源资源共享(CORS)是W3C标准,通过特殊HTTP头实现跨域。服务端设置Access-Control-Allow-Origin等头部信息控制访问权限。
// 服务端设置(Node.js示例)
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
next();
});
// 客户端简单请求示例
fetch('http://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data));
代理服务器方案
在同源策略下,通过同域服务器转发请求可绕过限制。以下是Node.js实现的简单代理:
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/proxy', async (req, res) => {
try {
const response = await axios.get('http://target-domain.com/api');
res.json(response.data);
} catch (error) {
res.status(500).send(error.message);
}
});
app.listen(3000);
postMessage跨窗口通信
window.postMessage API允许不同源的窗口间安全通信,适用于iframe嵌套等场景。
// 发送方窗口
const targetWindow = document.getElementById('iframe').contentWindow;
targetWindow.postMessage('Hello from parent!', 'https://child.example.com');
// 接收方窗口
window.addEventListener('message', (event) => {
if (event.origin !== 'https://parent.example.com') return;
console.log('Received:', event.data);
});
WebSocket协议跨域
WebSocket协议不受同源策略限制,适用于实时通信场景。
const socket = new WebSocket('wss://echo.websocket.org');
socket.onopen = () => {
socket.send('Hello Server!');
};
socket.onmessage = (event) => {
console.log('Received:', event.data);
};
Nginx反向代理配置
通过Nginx配置反向代理可避免前端跨域问题:
server {
listen 80;
server_name localhost;
location /api/ {
proxy_pass http://target-server.com/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
现代前端开发解决方案
开发环境下常用工具内置代理功能。以Vue CLI为例:
// vue.config.js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://target-domain.com',
changeOrigin: true,
pathRewrite: { '^/api': '' }
}
}
}
};
每种方案各有适用场景:JSONP适合老式浏览器但不支持POST;CORS需服务端配合;代理服务器增加架构复杂度但控制灵活;postMessage适合窗口间通信;WebSocket适合实时系统。应根据项目需求选择合适方案或组合使用。
3669

被折叠的 条评论
为什么被折叠?



