GX博客

分享个人 Full-Stack JavaScript 项目开发经验

浏览器的同源策略与JSONP

浏览器的同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。标准的同源定义为,两个页面的协议、端口和域名都相同。为了实现跨域数据访问,其中一种适用于主流浏览器的方式是JSONP


JSONP 的原理是利用同源策略中允许 <script src="..."></script> 标签嵌入跨域脚本。假如 https://www.a.com 页面中嵌入一个这样的脚本:

<script src="https://www.b.com?callback=callbackFunction"></script>

在该嵌入前,https://www.a.com 页面预先定义了一个名为 callbackFunction 的回调函数:

function callbackFunction (data){
  // 执行跨域数据请求后的相关操作
}

在 https://www.b.com 的服务器端(Koa2)接口返回数据形式如下:

const router = require('koa-router')();
router.get('/', async (ctx, next) => {
    if(ctx.query.callback) {
        ctx.body = ctx.query.callback + '(' + '"your_response"' + ')';
    } else {
        ctx.body = 'your_response';
    }
});

接口判断 GET 请求的参数 callback 是否存在。若存在,则返回其值的函数的调用,并在参数中传入服务器的响应内容。当 https://www.a.com 页面的跨域脚本加载完毕后,调用的正是预设的回调函数 callbackFunction。它获得了跨域请求的响应数据。这就是 JSONP 的基本原理。


如果你的项目依赖于 JQuery,则可使用它封装好的 $.ajax 方法,设置相关参数就可实现 JSONP 形式的跨域请求:

$.ajax({
  url: 'https://www.b.com',
  headers: {'X-Requested-With': 'XMLHttpRequest'},
  crossDomain: true,
  dataType: 'jsonp'
  // jsonp: 'callback' (用于指定回调函数名 URL 参数的 Key 的名称,默认为 'callback')
}).done(function(data) {
    // 执行跨域数据请求后的相关操作
}).fail(function(jqXHR, textStatus, errorThrown) {
    // ...
});

如果你的项目使用的是 Fetch,因为 JSONP 并不是它的标准 API,所以你可以使用如fetch-jsonp这样的库来实现。


了解更多浏览器同源策略的延申说明,请点这里

了解如何通过跨源资源共享(CORS),设置 Access-Control-* 响应标头方式实现跨域资源访问,请点击这里

版权声明:

本文为博主原创文章,若需转载,须注明出处,添加原文链接。

https://leeguangxing.cn/blog_post_21.html