同源策略:协议号-域名-端口号完全一致 12
- 跨域问题是由浏览器的同源策略引
- 同源策略的目的是保护用户的隐私和数据安全,防止恶意网站获取用户的敏感信息或进行未授权的操作
- 减少网络攻击:跨站脚本攻击XSS/跨站请求伪造CSRF
解决方案
1. JSONP [JSON with Padding]
<script>
可以跨域加载资源
前端动态创建<script>标签,并且设置其src为url[跨域]+回调函数[用于处理服务端返回的数据]: http://xxx?cb=callback
优:
- 简单易用
- 兼容性好
- 支持跨域请求
劣:
- 安全性问题:因为是在前端通过动态加载脚本实现的,有被恶意注入脚本的风险
- 只支持Get请求
- 依赖服务端支持
2. 常用
CORS [跨域资源共享]
一种机制
服务器通过设置响应头告知浏览器不要拒绝接受服务器的响应
- Access-Control-Allow-Origin: http://xxx:3000[特定域名] / *[所有域名]
- Access-Control-Allow-Methods: 指定允许的请求方法
- Access-Control-Allow-Headers: 指定允许的自定义请求头
3. domain
- 域名需满足domain方法的限制,即二级域名相同:example.com
- 父级页面需要在设置document.domain之前定义需要共享的变量/对象
- 子级页面可以通过 window.parent 来访问父级页面的属性/变量,但需要确保父级页面已经加载完成并且两者的域名设置已生效。
例:
页面A:parent.example.com
页面B:child.example.com
实现A与B跨域通信
// parent
<body>
<iframe src="http://child.example.com/child.html"></iframe>
<script>
var sharingMsgFormParent = 'xxxx';
document.domain = 'example.com';
</script>
</body>
// child
<script>
var sharingMsgFromChild = 'from me';
document.domain = 'example';
// 访问父级页面的变量
window.parent.sharingMsgFormParent
</script>
4. postMessage
配合<iframe>
使用,利用浏览器的同源策略,将不同域嵌套到不同的iframe
中,通过postMessage
实现跨文档通信
<body>
<iframe id="iframe" src="http://test.com/test"></iframe>
<script>
const iframe = document.getElementById('iframe');
iframe.onload() {
const data = { xx: 1 };
// 发送
iframe.contentWindow.postMessage(JSON.stringify(data), 'http://test.com');
}
// 监听来自其他页面的消息
window.addEventListener('message', (e) => {
// e.data
})
</script>
</body>
优:
- 安全性好:能够避免XSS
- 灵活性高
- 适用性广泛
劣:
- 复杂性高
- 性能消耗大:使用iframe可能会引入额外的网络请求和资源加载,有页面加载时的性能有一定影响
- 兼容性差: 旧版本浏览器可能不支持
5. 常用
反向代理
开发环境:通过脚手架或webpack配置devSever下的proxy选项,将/api开头的请求转发到真实服务器上
生产环境:使用nginx配置反向代理
// webpack.config.js
module.exports = {
devServer: {
// 一对一
api: {
target: 'http://example.com',
changeOrigin: true, // target是域名的话,需要设为true
secure: false, // 设置支持https协议的代理
},
// 多个特定路径代理到同一个目标
proxy: [
{
context: ['/api1', '/api2'],
target: 'http://example.com'
}
]
}
}