JSONP 是如何实现跨域的?

大家好,我是前端西瓜哥。今天讲 JSONP。

JSONP,是 JSON with Padding 的缩写,字面上的意思就是 “填充 JSON”。JSONP 是解决跨域请求的一种方案,我们先了解下跨域请求是什么。

跨域

浏览器在跨域发送 Ajax/fetch 请求时,会触发浏览器的同源策略,导致请求失败。

只要协议、域名、端口有一个不同,那浏览器就会认为是跨域。比如你在 a.com 下通过 Ajax 请求 b.com/api/book,默认情况下就被浏览器拦截,导致无法获得返回数据。

具体跨域的知识点,可以看我的这篇文章《为什么浏览器不能跨域发送 ajax 请求?

JSONP 怎么跨域?

既然 Ajax 不能发送跨域请求,那我们不用 Ajax,改用 script 标签。

HTML 下的 script 标签会指向一个脚本地址,这个地址允许跨域,浏览器会加载这个脚本然后执行。

除了 script 标签, link、img 等标签的请求也是允许跨域的。

下面以通过用户 id 获取用户信息为例。

前端实现

在 script 标签的 src 上,我们指定好需要服务器进行填充的回调函数名 setUser,并带上用户 id。

<script src="http://b.com:4000/user?id=2&callback=setUser"></script>

上面这种直接这样写到 HTML 里不太灵活,我们改写成下面这样。

let user = null;

function setUser(user{
  // 保存用户信息
  window.user = user;
  
  // 输出到页面上,看看效果。
  document.body.append(
    JSON.stringify(user);
  );
}

function getUserById(id{
  const script = document.createElement('script');
  script.src = `http://b.com:4000/user?id=${id}&callback=setUser`;
  document.body.appendChild(script);
}

document.querySelector('button').onclick = function() {
  getUserById(2);
}

后端实现

然后是服务端的处理,这里我用了 Nodejs 的 Express 框架。

const app = express();

// ...

const map = {
  1: { name'fe_watermelon' },
  2: { name'前端西瓜哥' }
};

// 例子:/user?id=2&callback=setUser
app.get('/user', (req, res, next) => {
  const { id, callback } = req.query;
  res.send(`${callback}(${JSON.stringify(map[id])})`);
});

// ...

服务端从 url 的请求字段中提取出 id ,找到对应的用户信息(通常为 JSON 的形式),配合要填充的回调函数 setUser,组装成字符串  setUser({"name":"前端西瓜哥"})

这个内容会作为脚本内容返回给前端,前端运行这个脚本后,就会执行全局作用域下的 setUser 函数,这个函数还会拿到用户信息,将其保存下来。

演示效果

结尾

JSONP 是一种解决跨域的方案,但一般比较少用到。

因为 JSONP 并不是标准,也不安全,服务端代码没写好会有代码注入的风险,且无法防范跨站请求伪造(CSRF)攻击。

我们也注意到要兜住返回的数据,必须定义一个全局的函数,在如今主流的模块化(变量隔离在各个模块中不暴露到全局)写法下有点格格不入。

我是前端西瓜哥,喜欢写技术文章,欢迎关注我。


相关文章,

为什么浏览器不能跨域发送 ajax 请求?

浏览器跨域请求的机制:CORS

HTTP 头字段 Origin、Host 和 Referer 有什么区别?

关注公众号,后台回复 「字节」,即可获得字节前端面试资料

本文使用 文章同步助手 同步

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容