JSONP能解决跨域的原理:
- 一句话:
<script>标签能受到限制的从其他的域加载
什么是JSONP
在讲跨域之前,先讲一下什么是JSONP,JSONP是“JSON with padding”的缩写,是web服务流行的JSON变体,JSONP看起来和JSON一样,只是包在一个函数调用中
callback({"name":"Apus"})
JSONP格式包括两个部分:
- 回调
- 数据
下面是一个典型的JSONP请求:
http://xxx//json/?callback=handleResponse
JSONP请求通常支持字符串的形式指定回调函数,比如这个例子就是指定回调函数handleReponse()
- 下面举个例子
function handleRseponse(response){
console.log()
let script = document.createElement("script");
script.src = "http://xxx//json/?callback=handleResponse";
document.body.insertBefore(script,document.body.firstChild);
}
- JOSNP是有效的js,所以JSONP会在响应加载之后立即执行
为什么 <script> 可以跨域?
浏览器的同源策略会限制大多数 AJAX 请求(如 XMLHttpRequest 或 fetch),不能访问不同源的数据。但 <script>、<img>、<link> 等标签不受这个限制,因为它们被认为是安全的资源请求。同时他们的设计初衷就是为了引入加载外部资源。
JSONP 的工作原理:
场景:
你的网站(前端域名):http://a.com
目标 API(后端域名):http://b.com/data
由于不同源,直接用 fetch('http://b.com/data') 会被浏览器拦截。
JSONP 解决方案:
-
客户端定义一个全局函数:
function handleResponse(data) { console.log('接收到的数据:', data); } -
动态插入
<script>,并把函数名通过查询参数传给服务器:const script = document.createElement('script'); script.src = 'http://b.com/data?callback=handleResponse'; document.body.appendChild(script); -
后端返回一段 JavaScript,而不是纯 JSON:
// 服务器返回内容: handleResponse({ name: 'ChatGPT', age: 3 }); -
浏览器执行这段脚本,自动调用你传给它的函数(
handleResponse),完成跨域数据获取。
JSONP 的限制:
| 限制点 | 描述 |
|---|---|
| 请求方式 | 只能使用 GET 方法(不能 POST) |
| 安全性差 | 存在 XSS 风险,因为它执行的是远程返回的 JS 代码 |
| 只能读取数据 | 无法用于跨域写入(例如提交表单数据) |
| 服务端需配合 | 必须按照特定格式返回 callbackName(data) |
| 错误处理不友好 | script 标签加载失败不能拿到明确的错误信息 |
现代替代方案:
CORS(跨源资源共享):服务端设置Access-Control-Allow-Origin头,前端用fetch或axios即可发起跨域请求。proxy(开发阶段代理):前端 dev server 将请求转发,绕过跨域。
//配置
server: {
proxy: {
'/api/': {
//target: 'http://192.168.1.31:8855',
target: 'http://*****:8081',
changeOrigin: true
}
}
}
postMessage:iframe 或 window 之间通信。WebSocket、server-side proxy等也可以用于特定场景。
总结
JSONP 是通过
<script>标签加载远程返回的 JS 脚本(包含数据),从而实现跨域读取数据的“黑科技”,本质是执行远程脚本,不是 AJAX。