老项目维护中,JSONP 兼容性好但安全性低,仅支持 GET 请求;现代 CORS 方案安全性高且支持所有 HTTP 方法,是主流标准。若无需兼容 IE6-9 等老旧浏览器,优先迁移至 CORS。
先说结论:CORS 是现代 Web 跨域的标准解决方案,JSONP 仅建议用于无法修改服务器配置或必须兼容极老浏览器的遗留场景。
- 适合:新项目或可控制服务端的跨域需求优先选 CORS,仅需 GET 且服务端不可控时考虑 JSONP。
- 重点看:安全性上 CORS 通过 HTTP 头控制权限,JSONP 存在 XSS 风险且无法拦截错误。
- 别忽略:JSONP 无法携带 Cookie 且不支持 POST 请求,迁移时需评估业务依赖。
快速处理思路
若正在维护老项目,先确认浏览器兼容要求和服务端控制权限。若服务端可配置响应头,直接启用 CORS;若服务端不可控且需兼容 IE8 以下,保留 JSONP 但限制回调函数白名单。迁移时先在小流量接口验证 CORS 头是否生效,再逐步替换 JSONP 请求。
为什么会这样
根本区别在于实现机制不同,导致安全性和功能上限差异。JSONP 利用<script>标签不受同源策略限制的特性,动态加载并执行服务器返回的 JavaScript 代码,本质是代码执行而非数据请求。CORS 基于 HTTP 头部字段(如 Access-Control-Allow-Origin),由浏览器和服务端协商权限,属于标准的资源共享机制。因此 JSONP 只能 GET 且易受 XSS 攻击,CORS 支持所有方法且由浏览器强制校验。
分步处理
第一步,检查服务端是否支持配置 HTTP 响应头。若支持,添加 Access-Control-Allow-Origin 指定允许域,避免使用通配符*涉及凭证场景。第二步,前端将 XMLHttpRequest 或 fetch 请求替代<script>标签加载方式。第三步,若必须保留 JSONP,限制回调函数名为固定值或白名单,防止任意代码执行。第四步,移除全局回调函数污染,改用模块化封装处理响应数据。
怎么验证是否生效
打开浏览器开发者工具 Network 面板,查看跨域请求的响应头。CORS 生效时可见 Access-Control-Allow-Origin 字段且值匹配当前域名。JSONP 生效时查看 Script 请求状态码是否为 200 且回调函数正确执行。若 CORS 报错,检查控制台是否有 Preflight OPTIONS 请求被拒绝或缺少 Access-Control-Allow-Methods 头。
常见坑
JSONP 无法捕获 404 或 500 错误,只能靠超时判断,容易漏掉服务端异常。CORS 携带 Cookie 时需同时设置 Access-Control-Allow-Credentials 为 true 且 Origin 不能为*。老项目迁移时,注意 JSONP 默认发送的 Content-Type 可能与 CORS 不同,服务端需兼容解析。部分老旧浏览器对 CORS 预检请求缓存策略不一致,可能导致重复 OPTIONS 请求影响性能。
常见问题
JSONP 能发送 POST 请求吗?
不能,JSONP 依赖<script>标签只能发起 GET 请求。
CORS 配置了为什么还是跨域报错?
检查服务端是否漏配 Access-Control-Allow-Methods 或请求头未通过预检。
老项目必须用 JSONP 吗?
不一定,若不需要兼容 IE6-9,建议通过反向代理或 CORS 解决。
JSONP 存在什么安全风险?
存在 XSS 风险,因为服务器返回的脚本会被直接执行,可能注入恶意代码。
参考来源
- 跨域解决方案 JSONP 和 CORS 对比分析
- jsonp 的优缺点
- HoRain 云`--CORS` 与 JSONP:跨域终极对决
- 前端跨域解决方案实践:JSONP 与 CORS 对比
- CORS 与 JSONP:跨域访问的两种方式及其安全性对比-CSDN 博客