CORS跨域学习
以下是关于浏览器跨域知识的系统性总结,包含核心原理、解决方案及实践注意事项:
一、跨域的本质:同源策略
-
同源策略定义
浏览器核心安全机制,限制不同源(协议、域名、端口需完全相同)的脚本或资源交互。例如:
•http://a.com
与https://a.com
(协议不同)跨域•
http://a.com:80
与http://a.com:8080
(端口不同)跨域•
http://a.com
与http://api.a.com
(子域名不同)跨域。 -
限制范围
• 数据访问:无法直接读取跨域的Cookie、LocalStorage、DOM元素。• 网络请求:AJAX/Fetch默认禁止跨域请求(但请求仍会发送,响应被浏览器拦截)。
• 特殊标签例外:
<script>
、<img>
等标签的src
属性可跨域加载资源,但内容不可被脚本直接读取。 -
安全意义
防止恶意网站通过CSRF(跨站请求伪造)或XSS(跨站脚本攻击)窃取用户数据。例如,用户登录银行网站后访问恶意网站,若无同源策略,后者可能通过脚本直接操作银行账户。
二、跨域解决方案全景
-
CORS(跨域资源共享)
• 原理:服务端通过响应头声明允许跨域的源、方法及头信息,浏览器根据响应头放行请求。◦ 简单请求:直接发送,响应头需包含
Access-Control-Allow-Origin: *
或具体域名。◦ 预检请求(OPTIONS):复杂请求(如PUT/DELETE)需先发送OPTIONS预检,通过后再发实际请求。
• 服务端配置示例(Node.js):
res.setHeader('Access-Control-Allow-Origin', 'http://your-frontend.com'); res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
-
JSONP(JSON with Padding)
• 原理:利用<script>
标签不受同源策略限制的特性,通过动态创建标签发起GET请求,服务器返回回调函数包裹的数据。• 示例:
<script src="http://api.com/data?callback=handleData"></script> <!-- 服务器返回:handleData({"data": "value"}); -->
• 缺点:仅支持GET请求,存在XSS风险(需严格过滤回调函数名)。
-
代理服务器
• 开发环境:前端框架(如Vue/React)配置本地代理,将请求转发至同源后端,规避浏览器限制。// Vue示例(vue.config.js) devServer: { proxy: { '/api': { target: 'http://real-api.com' } } }
• 生产环境:使用Nginx反向代理,统一处理跨域头并转发请求。
location /api { proxy_pass http://backend-server; add_header 'Access-Control-Allow-Origin' 'http://your-domain.com'; }
-
其他方案
• WebSocket:全双工通信协议,握手阶段走HTTP,后续连接不受同源限制。• postMessage:跨窗口通信API,需验证消息来源。
• 修改document.domain:仅适用于同父域的子域名跨域(如
a.example.com
与b.example.com
)。
三、实践注意事项
-
安全性
• 生产环境避免使用Access-Control-Allow-Origin: *
,应明确指定允许的域名。• JSONP需验证回调函数名合法性,防止恶意脚本注入。
-
预检请求优化
• 设置Access-Control-Max-Age: 86400
缓存预检结果,减少OPTIONS请求次数。• 使用HTTP/2多路复用提升性能。
-
特殊场景处理
• 携带凭证(如Cookie):需设置Access-Control-Allow-Credentials: true
,且Access-Control-Allow-Origin
不能为*
。• 本地文件跨域:Chrome启动参数加
--allow-file-access-from-files
(仅开发测试用)。
四、方案选择建议
场景 | 推荐方案 | 说明 |
---|---|---|
现代Web应用 | CORS + Nginx反向代理 | 标准化、安全可控。 |
本地开发调试 | 前端代理(如Vue/React) | 便捷快速。 |
兼容老旧浏览器 | JSONP(谨慎使用) | 仅支持GET,需安全过滤。 |
实时通信(如聊天) | WebSocket | 长连接、低延迟。 |
参考资料
• 同源策略定义与示例:[MDN文档]。 https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy?redirectlocale=zh-CN
• CORS配置详解:[阮一峰CORS教程]。 https://www.ruanyifeng.com/blog/2016/04/cors.html
• Nginx代理实战:[跨域问题一文讲透]。
跨域是指从一个域名的网页去请求另一个域名的资源。它是由浏览器的同源策略造成的,是浏览器为了提高网站的安全性对JavaScript施加的限制,使浏览器不能执行其他网站的脚本。跨域的更加严格的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。
DOM同源策略:禁止对不同源页面DOM进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
XmlHttpRequest同源策略:禁止使用XHR对象向不同源的服务器
地址发起HTTP请求。
-
同源策略解释
它能帮助阻隔恶意文档,减少可能被攻击的媒介。例如,它可以防止互联网上的恶意网站在浏览器中运行 JS 脚本,从第三方网络邮件服务(用户已登录)或公司内网(因没有公共 IP 地址而受到保护,不会被攻击者直接访问)读取数据,并将这些数据转发给攻击者。 -
具体可能的问题场景
-
cors协议
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。 -
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。 -
简单请求和非简单请求
-
处理逻辑不通,简单请求直接请求,非简单请求会有一个预请求,浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。