JSONP(JSON with Padding)是一种通过动态创建 <script>
标签来实现跨域请求的技术。它利用了浏览器允许从不同源加载 JavaScript 文件的特性,从而绕过同源策略的限制。
JSONP 原理
- 客户端发起请求:客户端创建一个
<script>
标签,并将其src
属性设置为包含回调函数名的 URL。 - 服务器响应:服务器接收到请求后,生成一个包含回调函数调用和数据的 JavaScript 代码,并将其返回给客户端。
- 执行回调:浏览器加载并执行返回的 JavaScript 代码,从而触发客户端定义的回调函数,处理返回的数据。
示例代码
客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSONP Example</title>
<script type="text/javascript">
// 定义回调函数
function handleResponse(data) {
console.log("Received data:", data);
}
// 动态创建 <script> 标签
function makeJsonpRequest(url) {
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}
// 发起 JSONP 请求
window.onload = function() {
var url = "http://example.com/api?callback=handleResponse";
makeJsonpRequest(url);
};
</script>
</head>
<body>
</body>
</html>
服务器端代码(假设使用 Node.js 和 Express)
const express = require('express');
const app = express();
const port = 3000;
app.get('/api', (req, res) => {
const callback = req.query.callback; // 获取回调函数名
const data = { message: 'Hello, world!' }; // 要返回的数据
const response = `${callback}(${JSON.stringify(data)})`; // 构造 JSONP 响应
res.setHeader('Content-Type', 'application/javascript'); // 设置响应类型为 JavaScript
res.send(response); // 发送响应
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
详解
-
客户端部分:
handleResponse
是客户端定义的回调函数,用于处理服务器返回的数据。makeJsonpRequest
函数动态创建一个<script>
标签,并将其src
属性设置为包含回调函数名的 URL。- 当页面加载时,
window.onload
事件触发,调用makeJsonpRequest
函数发起 JSONP 请求。
-
服务器部分:
- 使用 Express 框架创建一个简单的服务器。
- 在
/api
路由中,获取查询参数中的回调函数名callback
。 - 构造一个包含回调函数调用和数据的字符串,并将其作为 JavaScript 代码返回。
- 设置响应头
Content-Type
为application/javascript
,以确保浏览器将其作为 JavaScript 代码执行。
注意事项
- 安全性:由于 JSONP 是通过动态插入脚本的方式实现跨域请求,因此存在安全隐患。如果服务器返回的 JavaScript 代码被恶意篡改,可能会执行任意代码。因此,在使用 JSONP 时需要确保服务器端的代码安全。
- 现代替代方案:随着 CORS(跨域资源共享)的普及,JSONP 的使用逐渐减少。CORS 提供了一种更安全、更灵活的方式来实现跨域请求。建议在新项目中优先考虑使用 CORS。