什么是JSONP,它为何被创建?

什么是JSONP,它为何被创建?

技术背景

在Web开发中,浏览器存在同源策略限制,即浏览器不允许页面向不同源(协议、端口、主机任一不同)的服务器直接发起AJAX请求。例如,在 example.com 域名下的页面无法直接向 example.net 域名的服务器发起请求。这一限制是为了保护用户信息安全,防止恶意网站通过跨域请求获取用户敏感数据。但在实际开发中,有时确实需要从不同源的服务器获取数据,JSONP(JSON with Padding)就是为了解决这个问题而诞生的一种跨域数据交互技术。不过,JSONP也存在一些缺点,如今在大多数情况下,更推荐使用CORS(Cross-Origin Resource Sharing)来处理跨域请求。

实现步骤

1. 客户端创建script标签

客户端通过创建 <script> 标签来发起请求,因为 <script> 标签不受同源策略的限制。例如:

1
2
3
4
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.example.net/sample.aspx?callback=mycallback';
document.getElementsByTagName('head')[0].appendChild(script);

2. 服务器处理请求

服务器接收到请求后,会检查是否包含 callback 参数。如果包含,服务器会将返回的JSON数据包装在回调函数中。例如,原本返回的JSON数据为 { foo: 'bar' },在JSONP请求下,服务器会返回 mycallback({ foo: 'bar' });

3. 客户端定义回调函数

客户端需要在全局作用域中定义与 callback 参数值相同的回调函数,用于处理服务器返回的数据。例如:

1
2
3
function mycallback(data) {
alert(data.foo);
}

<script> 标签加载完成后,会自动执行回调函数,从而实现跨域数据的处理。

核心代码

纯JavaScript实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<title>JSONP示例</title>
<meta charset="UTF-8" />
</head>
<body>
<input type="text" id="username" placeholder="Enter Your Name" />
<button type="submit" onclick="sendRequest()"> Send Request to Server </button>
<script>
"use strict";
// 构造script标签
function requestServerCall(url) {
var head = document.head;
var script = document.createElement("script");
script.setAttribute("src", url);
head.appendChild(script);
head.removeChild(script);
}

// 预定义回调函数
function jsonpCallback(data) {
alert(data.message);
}

// 获取输入框引用
var username = document.getElementById("username");

// 发送请求到服务器
function sendRequest() {
requestServerCall("http://localhost/PHP_Series/CORS/myService.php?callback=jsonpCallback&message=" + username.value + "");
}
</script>
</body>
</html>

服务器端PHP代码

1
2
3
4
5
6
7
<?php
header("Content-Type: application/javascript");
$callback = $_GET["callback"];
$message = $_GET["message"] . " you got a response from server yipeee!!!";
$jsonResponse = "{\"message\":\"" . $message . "\"}";
echo $callback . "(" . $jsonResponse . ")";
?>

jQuery实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(document).ready(function () {
$.ajax({
url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
dataType: 'jsonp',
success: function (dataWeGotViaJsonp) {
var text = '';
var len = dataWeGotViaJsonp.length;
for (var i = 0; i < len; i++) {
var twitterEntry = dataWeGotViaJsonp[i];
text += '<p><img src = "' + twitterEntry.user.profile_image_url_https + '"/>' + twitterEntry['text'] + '</p>';
}
$('#twitterFeed').html(text);
}
});
})
</script>
</head>
<body>
<div id="twitterFeed"></div>
</body>
</html>

最佳实践

  • 使用CORS替代:在现代Web开发中,尽量使用CORS来处理跨域请求。CORS是一种更安全、更标准的跨域解决方案,服务器可以通过设置响应头来控制哪些源可以访问资源。
  • 验证回调函数名:在服务器端,应该对客户端传递的回调函数名进行严格验证,防止XSS攻击。例如,只允许合法的函数名,避免使用用户输入的原始值。
  • 设置超时:由于JSONP请求没有标准的错误处理机制,可以设置超时来处理请求失败的情况。

常见问题

1. 只能进行GET请求

JSONP本质上是通过 <script> 标签发起请求,而 <script> 标签只能发起GET请求,因此无法使用JSONP进行POST等其他类型的请求。

2. 缺乏错误处理

JSONP请求没有标准的错误处理机制,无法像AJAX请求那样获取详细的错误信息。可以通过设置超时来处理请求失败的情况,但这种方法不够完善。

3. 安全风险

由于JSONP允许服务器返回可执行的JavaScript代码,如果服务器被攻击,可能会返回恶意代码,导致用户信息泄露。因此,在使用JSONP时,必须确保服务器的安全性。


什么是JSONP,它为何被创建?
https://119291.xyz/posts/2025-05-14.what-is-jsonp-and-why-was-it-created/
作者
ww
发布于
2025年5月14日
许可协议