JSONP跨域原理全解析

发布于:2025-05-30 ⋅ 阅读:(23) ⋅ 点赞:(0)

JSONP(JSON with Padding)是一种绕过浏览器同源策略限制、实现跨域数据请求的“hack”式方案。其核心原理和流程如下:

  1. 同源策略限制
    浏览器为了安全,只允许页面从与当前页面相同协议、域名、端口的服务器加载数据。而 <script><img><link> 等标签对跨域不受同源策略限制——只要目标资源返回有效内容,浏览器就会加载并执行。

  2. 利用 <script> 标签跨域
    JSONP 利用该特性:前端通过动态创建一个 <script> 标签,设置其 src 属性指向目标跨域接口,并带上一个回调函数名参数,比如:

    <script>
      function handle(data) {
        console.log('服务器返回的数据:', data);
      }
      var script = document.createElement('script');
      script.src = 'https://api.example.com/data?callback=handle';
      document.head.appendChild(script);
    </script>
    
  3. 服务器端“打包”返回
    服务器接收到请求后,不是直接返回纯 JSON,而是把 JSON 数据“包裹”(padding)在指定的回调函数调用里,例如:

    handle({
      "name": "Alice",
      "age": 30
    });
    

    浏览器加载这个脚本时,就会立即执行 handle(...),把数据当作参数传入页面上事先定义好的回调函数。

  4. 流程图示

    1. 页面定义全局回调函数 handle
    2. 页面动态插入 <script src="...callback=handle">
    3. 浏览器向跨域服务器发送 GET 请求。
    4. 服务器将 JSON 数据封装成 handle(JSON) 格式的脚本返回。
    5. 浏览器下载并执行该脚本,触发全局回调函数,拿到数据。
  5. 优缺点

    • 优点
      • 简单,无需 CORS 支持即可跨域请求 GET 接口。
    • 缺点
      • 仅支持 GET 请求,不支持 POST、PUT 等。
      • 安全性较差,容易受到 XSS 攻击(调用任意脚本)。
      • 回调地狱:多个并发请求时需要管理不同回调名。
  6. 现代替代
    随着 CORS(跨域资源共享)和 fetch/XMLHttpRequest 支持跨域请求,JSONP 已被逐步淘汰,仅在极少数不支持 CORS 的老旧环境下使用。


示例代码

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>JSONP 示例</title>
  <script>
    // 全局回调函数
    function jsonpCallback(data) {
      document.getElementById('output').textContent =
        'Hello, ' + data.name + ',你 ' + data.age + ' 岁了!';
    }
    // 动态加载 JSONP 脚本
    function loadData() {
      const script = document.createElement('script');
      script.src = 'https://api.example.com/user?callback=jsonpCallback';
      document.head.appendChild(script);
    }
  </script>
</head>
<body>
  <button onclick="loadData()">获取用户信息</button>
  <div id="output"></div>
</body>
</html>

上述例子中,当点击按钮时,会向 https://api.example.com/user?callback=jsonpCallback 发起跨域请求,服务器返回:

jsonpCallback({ "name": "Bob", "age": 25 });

浏览器执行该脚本,直接调用页面上的 jsonpCallback,完成数据读取和展示。


网站公告

今日签到

点亮在社区的每一天
去签到