同源策略与跨域安全
同源策略的基本概念
同源策略是浏览器实施的一种重要安全机制,它限制了一个源的文档或脚本如何与另一个源的资源进行交互。所谓"同源",指的是协议、域名和端口号完全相同。例如:
https://example.com/page1
和https://example.com/page2
是同源https://example.com
和http://example.com
不同源(协议不同)https://example.com
和https://sub.example.com
不同源(域名不同)https://example.com
和https://example.com:8080
不同源(端口不同)
同源策略主要影响以下操作:
- AJAX请求
- Web Storage和IndexedDB访问
- Cookie读取
- DOM访问(iframe间通信)
// 尝试跨域访问会触发同源策略限制
fetch('https://api.other-site.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('跨域请求被阻止:', error));
跨域资源共享(CORS)
CORS是现代浏览器支持的标准机制,允许服务器声明哪些外部源可以访问其资源。当需要跨域请求时,浏览器会自动发送一个预检请求(OPTIONS)来检查服务器是否允许实际请求。
简单请求与预检请求
简单请求需满足以下条件:
- 使用GET、HEAD或POST方法
- 仅包含安全的首部字段(Accept、Accept-Language等)
- Content-Type为application/x-www-form-urlencoded、multipart/form-data或text/plain
// 简单请求示例
fetch('https://api.example.com/data', {
method: 'GET',
headers: {
'Content-Type': 'text/plain'
}
});
非简单请求会触发预检:
// 会触发预检的请求
fetch('https://api.example.com/data', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'value'
},
body: JSON.stringify({key: 'value'})
});
服务器端CORS配置
Node.js Express示例:
const express = require('express');
const app = express();
// 基本CORS配置
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://trusted-site.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
// 处理预检请求
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
JSONP跨域技术
在CORS出现前,JSONP是常用的跨域解决方案。它利用<script>
标签不受同源策略限制的特性。
function handleResponse(data) {
console.log('收到数据:', data);
}
// 动态创建script标签
const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);
服务器需要返回包装在回调函数中的JSON数据:
// 服务器响应
handleResponse({
"name": "示例数据",
"value": 42
});
JSONP的局限性:
- 仅支持GET请求
- 缺乏错误处理机制
- 存在安全风险(XSS漏洞)
postMessage跨文档通信
对于不同源的iframe或窗口间通信,可以使用postMessage API。
// 发送消息到iframe
const iframe = document.getElementById('my-iframe');
iframe.contentWindow.postMessage({
type: 'data_update',
payload: { key: 'value' }
}, 'https://target-origin.com');
// 接收消息
window.addEventListener('message', (event) => {
// 验证来源
if (event.origin !== 'https://trusted-origin.com') return;
console.log('收到消息:', event.data);
});
跨域安全最佳实践
-
严格设置CORS头:
- 避免使用
Access-Control-Allow-Origin: *
- 明确指定允许的方法和头
- 避免使用
-
CSRF防护:
- 使用SameSite Cookie属性
- 实现CSRF令牌
<!-- 表单中包含CSRF令牌 -->
<form action="/transfer" method="POST">
<input type="hidden" name="_csrf" value="token-value">
<!-- 其他表单字段 -->
</form>
- 内容安全策略(CSP):
- 限制脚本来源
- 防止XSS攻击
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' https://trusted-cdn.com">
- 避免敏感信息暴露:
- 不要在前端代码中硬编码API密钥
- 使用环境变量或后端代理
WebSocket跨域安全
WebSocket协议本身不受同源策略限制,但仍需注意安全:
const socket = new WebSocket('wss://api.example.com/ws');
// 服务器应验证Origin头
socket.onopen = () => {
socket.send(JSON.stringify({ action: 'subscribe' }));
};
socket.onmessage = (event) => {
console.log('收到消息:', event.data);
};
现代跨域技术
- 代理服务器:
- 前端请求同源服务器
- 服务器转发请求到目标API
// 前端请求
fetch('/api/proxy', {
method: 'POST',
body: JSON.stringify({
url: 'https://target-api.com/endpoint',
method: 'GET'
})
});
- 反向代理:
- 使用Nginx配置
location /api/ {
proxy_pass https://target-api.com/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
- 跨域资源共享的扩展:
- 跨域资源共享策略(CORP)
- 跨域隔离状态
Cross-Origin-Resource-Policy: same-site
常见跨域场景解决方案
- 跨域Cookie:
- 设置
withCredentials
和Access-Control-Allow-Credentials
- 设置
fetch('https://api.example.com/auth', {
credentials: 'include'
});
- 跨域图片:
- 使用
crossOrigin
属性
- 使用
<img src="https://other-site.com/image.jpg" crossOrigin="anonymous">
- 字体跨域:
- 配置正确的CORS头
@font-face {
font-family: 'CustomFont';
src: url('https://other-site.com/font.woff2') format('woff2');
font-display: swap;
}
浏览器安全沙箱与跨域
现代浏览器实现了严格的沙箱机制,进一步增强了跨域安全:
-
站点隔离:
- 每个站点在独立进程中运行
- 防止Spectre等侧信道攻击
-
跨域策略文件:
crossorigin.xml
定义允许的跨域访问- Flash时代遗留,现代Web较少使用
-
CORB(跨域读取阻止):
- 浏览器阻止某些类型的跨域响应
- 如JSON、HTML、XML等敏感数据类型
性能优化与跨域
跨域请求可能影响性能,优化策略包括:
-
预加载:
<link rel="preconnect" href="https://api.example.com"> <link rel="dns-prefetch" href="https://cdn.example.com">
-
CDN加速:
- 使用同一CDN域名提供静态资源
- 减少DNS查询和TCP握手
-
HTTP/2优化:
- 多路复用减少连接开销
- 头部压缩降低传输量
新兴标准与未来趋势
-
WebAssembly跨域:
- 严格的模块安全限制
- 需要CORS和CORB保护
-
Portals API:
- 允许嵌入跨源内容
- 提供更好的用户体验
-
SharedArrayBuffer:
- 需要跨域隔离状态
- 高精度计时器限制
// 检查跨域隔离状态
if (crossOriginIsolated) {
// 可以使用SharedArrayBuffer等高级特性
const buffer = new SharedArrayBuffer(1024);
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn