JSONP原理详解——弄懂JSONP及其实现方法

定义

同源策略

首先我们要了解什么是同源策略,来看看百度百科的解释:

同源策略,它是由Netscape提出的一个著名的安全策略。
现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。
当一个浏览器的两个tab页中分别打开百度和谷歌的页面
当一个百度浏览器执行一个脚本的时候会检查这个脚本是属于哪个页面的
即检查是否同源,只有和百度同源的脚本才会被执行。

总结的来说,由于浏览器安全限制,数据是不可以直接跨域请求的,包括不同的根域名、二级域名、或不同的端口,除非目标域名授权你可以访问。想要解决同源策略实现传输,就需要跨域。而跨域的方式有很多种,JSONP就是其中的一种。

具体想了解更多,可以看看阮一峰老师的文章,讲解的非常详细:
https://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

JSONP的产生

我们发现,Web页面上调用js文件时则不受是否跨域的影响,不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<\script>、<\img>、<\iframe>。

而有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,并被原生js支持。

所以实现跨域的方案就出现了。我们可以调用跨域服务器上动态生成的js格式文件,也就是调用JSON文件,获取自己需要的数据。

后来逐渐形成了一种非正式的传输协议,也就是JSONP。该协议允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,客户端接收到响应后执行回调并且可以对数据进行各种需要的处理。

说到这里,我们来总结一下什么是JSONP
通过动态创建script标签,其scr指向非同源的url,并传递一个callback参数给服务端,服务器返回一个以callback参数作为函数名的函数的调用和一系列参数,页面接收到响应后执行回调并对数据进行处理。

接下来我们就把JSONP的完整过程来实现一遍。

实现JSONP

首先,我们要有一个请求方和响应方,请求方是一个网页的前端,也就是浏览器,响应方是另一个网页的后台,也就是服务器,两个网页时不同源的。

这里我们假设浏览器页面显示着一个数字100和一个打钱的按钮,服务器储存着页面显示的那个数字,要求在每按下打钱按钮的时候,浏览器显示的数字减一,并且服务端储存这个减后的数字,在下一次打开的时候显示减后的数字。这是一个跨域向非同源网站的服务器发送请求和接收响应的过程。
请求方:http://fang.com:8001
响应方:http://zeng.com:8002

先写好html:

image

接着就是写前端部分代码main.js,实现点击之后发送请求改变数字:

button.addEventListener(
  'click',(e)=>{
    let script = document.createElement('script')//创建script标签
    let functionName = 'fang' + parseInt(Math.random()*10000000,10)//设置调用函数名
    window[functionName] = function(result){
      if(result === 'success'){
        amount.innerText = amount.innerText - 1
      }else{

      }
    }
    script.src = `http://zeng.com:8002/pay?callback${functionName} `
    document.body.appendChild(script)//将能实现发送跨域请求的script标签插入html
    script.onload = function(e){
      e.currentTarget.remove()
      delete window[functionName]
    }
    script.onerror = function(){
      alert('fail')
      e.currentTarget.remove()
      delete window[functionName]
    }
    //完成传输后删除script标签
  }
)

搭建好服务器,就可以实现功能了。这个就是一个利用JSONP发送跨域和响应的过程。

JSONP的优点与缺点

优点

  • JSONP可以跨越同源策略,实现跨域传输,不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制
  • JSONP兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
  • 在请求完毕后可以通过调用callback的方式回传结果。将回调方法的权限给了调用方

缺点

  • 它只支持GET请求而不支持POST等其它类型的HTTP请求,因为script标签的scr只能进行GET请求
  • 它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
  • jsonp在调用失败的时候不会返回各种HTTP状态码。
  • 缺乏安全性。假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的,那么所有调用这个jsonp的网站都会存在漏洞,这样的话危险就不止在一个域名下。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的...
    西瓜w阅读 1,753评论 0 1
  • 前端如何使用proxyTable和nginx解决跨域问题 前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及...
    kangaroo_v阅读 1,234评论 0 33
  • AJAX 原生js操作ajax 1.创建XMLHttpRequest对象 var xhr = new XMLHtt...
    碧玉含香阅读 3,188评论 0 7
  • 前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容。 本文完整的源代码...
    浪里行舟阅读 2,933评论 0 32
  • 愿所有的青春都能被温柔以待,愿悲伤之河能幻化成希望的源泉,愿生活里的暗无天日都会被阳光打破。 电影源于生活也高于生...
    拾光若梦阅读 619评论 3 4