JSONP跨域靠动态插入script标签“借道”加载,CORS靠服务器在HTTP响应头里明确放行;两者不是替代关系,而是不同场景下的两种解法。现在的前端项目,只要涉及API接口对接,大概率绕不开跨域这两个字,理解jsonp跨域的原理,学会配置API的跨域资源共享,是每个前端开发的基本功,这篇文章不拽术语,用大白话把原理讲透,给出可以直接抄的配置步骤。

jsonp跨域的原理:为什么它能绕过浏览器拦截
要理解jsonp,先得知道浏览器为什么拦你,所谓同源策略,指的是协议、域名、端口三者一致才算同源,只要有一个对不上,浏览器就会把响应“扣下”,不让页面里的JS读取。
浏览器管得住XHR,管不住script标签
奇怪的地方在于——浏览器虽然拦截XMLHttpRequest/Fetch发起的跨域请求,却不拦截script、img、link这类带src属性的标签,页面里加载外域JS文件、CDN脚本是再正常不过的事,浏览器根本不管,jsonp的思路就是钻这个空子:用script标签去请求后端接口,后端配合着返回一段可执行的JS代码,而不是纯数据。
一次完整的jsonp请求流程
它的工作方式,像极了“传纸条”——前端写好一个函数,把函数名塞在URL查询参数里抛给后端,后端把数据塞进这个函数里返回,具体拆开看就三步:
- 前端定义一个回调函数,比如
handleResult,留着接收数据 - 动态创建一个script标签,设src为
https://api.example.com/data?callback=handleResult,塞进页面 - 后端解析到
callback参数,返回handleResult({“name”:”张三”})这样的JS代码,浏览器直接当成脚本执行,数据就顺理成章进了前端代码
整个过程中,前端没有发起任何“正经”的AJAX请求,而是借script标签的“豁免权”拿到了数据。jsonp跨域的原理一句话归纳:利用script标签天然可跨域的特性,以函数调用的方式传递数据。
jsonp的两个明显短板
- 只支持GET请求——因为script标签加载本质上是一次GET,没法发POST,这就限制了请求体大小和数据敏感度
- 错误处理弱——接口挂了只能靠script的onerror事件兜底,拿不到HTTP状态码,调试起来比较吃力
行业共识认为,jsonp更适用于轻量级的数据读取场景,比如天气接口、股票行情、公开的资讯列表,老牌API提供商的JSONP接口至今还在用,原因就是接入成本极低,服务端改几行代码就能支持。
配置API的跨域资源共享:CORS才是现代应用的主航道
如果你要对接的是自家后端,或者要发POST/PUT这类复杂请求,CORS才是正解,CORS全称是跨域资源共享,它的思路跟jsonp完全相反——不躲不闪,直接告诉浏览器“这个来源的数据可以放行”。
CORS是怎么工作的
浏览器在发起跨域请求时,会先发一个“预检请求”(OPTIONS),问服务器:我想从这个域名发POST,带JSON格式,你让不让?服务器收到后用响应头回答:让,浏览器确认没问题,才发出真正的业务请求。
关键就在服务器返回的这几个响应头上,核心配置就三项:
Access-Control-Allow-Origin:指定允许的请求源,可填具体域名或(通配所有域名)Access-Control-Allow-Methods:允许的方法列表,如GET、POST、PUT、DELETEAccess-Control-Allow-Headers:允许的自定义请求头,比如Content-Type、Authorization
用Nginx给接口配置跨域
如果你的API在Nginx后面,那是改动最小的方式,在Nginx的server块或location块里,加上下面这段配置即可:

location /api/ {
add_header Access-Control-Allow-Origin ;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
这段配置覆盖了大多数项目的基本需求,表示所有域名都能访问,如果只让某个域名用,换成https://yourdomain.com就行。OPTIONS请求直接返回204,让预检快速通过,不用进后端逻辑。
Node.js/Express后端开启CORS
Express框架下用cors中间件是最省事的路子:
const cors = require('cors');
app.use(cors());
这一行就默认允许所有跨域请求,要定制规则时,改成传配置对象:
app.use(cors({
origin: ['https://admin.example.com', 'https://www.example.com'],
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));
credentials: true这个参数要留意——如果你需要跨域携带Cookie,origin就不能写,必须明确指定具体域名,这是浏览器的安全限制。
Spring Boot的跨域配置
Java后端用Spring Boot的话,用CorsRegistry做全局配置:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/")
.allowedOrigins("https://yourdomain.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("")
.allowCredentials(true)
.maxAge(3600);
}
}
maxAge用来指定预检请求结果缓存时间,单位是秒,能减少重复预检的次数,提升接口响应速度。
jsonp和cors怎么选:按场景对号入座
很多刚接触跨域的朋友容易纠结,“我到底该用哪个?”这俩不冲突,甚至可以在一个项目里共存,判断标准就三条:
- 项目里已有第三方API只提供jsonp接口,比如一些老牌数据服务商——用jsonp
- 自家前后端分离项目,要发POST、要处理敏感数据——用CORS
- 开发预算有限、地图或支付这类SDK提供的后端接口已配好CORS——直接用CORS,前端啥都不用改
JSONP的兼容性没有想象中那么大优势
网上还在传“jsonp兼容IE老版本,CORS不支持IE8/9”——这个说法在2026年已经没多大意义,据业内专家指出,当前主流浏览器的市场占比已相当高,绝大多数用户的浏览器版本都全面支持CORS,为了极少数旧版本客户端去选jsonp,并不划算。
一个真实场景:小程序对接第三方电商API
比如你开发一个小程序前端,需要对接第三方电商平台的商品查询接口,对方提供了两种接入方式:jsonp接口和CORS配置,这时候怎么选?如果只是商品信息这种公开数据,两者都行;但如果你要提交订单、处理支付回调,就必须选CORS,因为支付信息需要POST方式提交,jsonp根本做不了,在开发联调阶段,可以先用jsonp快速验证返回数据格式,后续正式上线再切成CORS。

配置API的跨域资源共享时常见的几个坑
加了响应头还是报跨域错误
大概率是你只配了Access-Control-Allow-Origin,漏了其他头,前端如果发的是application/json格式,还要配Access-Control-Allow-Headers,用Axios的话,改Content-Type、加Authorization都是跨域高频诉求,这几个响应头建议一次性配齐。
带了Cookie就是失败
浏览器默认跨域请求不携带Cookie,你想跨域带Cookie的话,前端要设置withCredentials: true(XHR)或credentials: 'include'(fetch),后端必须同时配Access-Control-Allow-Credentials: true且不能使用``通配符,两边同时满足,Cookie才发得出去。
预检请求把后端搞崩了
有些后端同学不清楚OPTIONS请求是什么,直接当成业务请求处理,结果报错,CORS的预检请求本质上是一种“询问”,你看到OPTIONS来了,应在业务路由之前统一拦截并返回204,别让逻辑代码碰它。
常见问题解答
jsonp跨域接口为什么不能发POST请求
jsonp通过script标签的src发起请求,而src本身就是GET方式,没法携带请求体,理论上可以借助其他技巧伪造,但没必要——需要POST就老老实实用CORS。
配置API的跨域资源共享后,前端还需要做什么吗
大部分情况不用,如果请求要携带Cookie或自定义请求头,前端需要配置withCredentials和请求头字段,使用Axios时,在请求配置中声明这两项即可,其他交给浏览器自动处理。
jsonp跨域方案今天还有没有使用价值
在一些公开的开放数据平台、老牌统计服务商、简单工具类API中依然存在,它胜在简单——不需要后端开发专门处理预检请求,加一个回调函数参数就能用,前提是接口不涉及敏感数据,仅做查询用途。
跨域问题的本质是浏览器的安全策略,jsonp和CORS只是绕行或开门的两种路径,理解jsonp跨域的原理能拓宽你在老旧接口场景下的处理思路,学会配置API的跨域资源共享则能应对绝大多数现代应用开发需求。两者结合,跨域这个坎就基本迈过去了。
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/554187.html