JSONP原理以及实现

JSONP原理

跨域

因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax 请求会失败。

也就是说,没有同源策略的情况下,A 网站可以被任意其他来源的 Ajax 访问到内容。如果你当前 A 网站还存在登录态,那么对方就可以通过 Ajax 获得你的任何信息。当然跨域并不能完全阻止 CSRF。

然后我们来考虑一个问题,请求跨域了,那么请求到底发出去没有? 请求必然是发出去了,但是浏览器拦截了响应。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么 Ajax 就不会。因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax 可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟是发出去了。

解决方案有很多,现在说一下jsonp的实现

原理

通俗的说就是利用script标签中的src属性能请求js代码资源的原理,从服务器请求一些js代码来执行。

var express = require('express');
var router = express.Router();

router.get('/',function(req,res,next){
  res.send(`JSONP_Practice_By_Joey_Tribiani`)
});
module.exports = router;

上面就是我们一个简单的服务器端的代码,get方式访问’/'路由返回数据,这样我们在客户端利用script标签的src属性请求的时候,得到这个结果,但是这里出现问题了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YahaADKE-1584809454903)(C:\Users\joey\AppData\Roaming\Typora\typora-user-images\image-20200322001952871.png)]

报了语法错误,原因就是script标签请求到js代码后会立即执行,而我们返回的是字符串,js引擎是无法当做js代码执行的,因此我们需要简单优化下,返回的数据我们可以用模板运算符拼接一下

var express = require('express');
var router = express.Router();

router.get('/',function(req,res,next){
  res.send(`console.log("JSONP_Practice_By_Joey_Tribiani")`)
});
module.exports = router;

这样子我们就如愿以偿的拿到了想要的结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-35NKUake-1584809454905)(C:\Users\joey\AppData\Roaming\Typora\typora-user-images\image-20200322002252020.png)]

JSONP 使用简单且兼容性不错,但是只限于 get 请求。

在开发中可能会遇到多个 JSONP 请求的回调函数名是相同的,这时候就需要自己封装一个 JSONP,以下是简单实现

 function jsonpFn(url,cb){
            const createSscript = document.createElement("script");
            createSscript.src=`${url}?callback=${cb}`;
            createSscript.src=`${url}?callback=${cb}`;
            document.body.appendChild(createSscript);
            document.querySelector("body>script:last-child").remove();
        }

这里注意了,我们是把自己想要调用的函数的函数名传过去,所以传参数cb的时候要传字符串,然后由于我们是以query的方式传递信息,所以服务端需要配合修改

var express = require('express');
var router = express.Router();

router.get('/',function(req,res,next){

  const cb = req.query.callback  //这里就拿到了我们传的函数名
  console.log(cb);
  
  res.send(`${cb}("JSONP_Practice_By_Joey_Tribiani")`)
});

module.exports = router;

这样一个简单的jsonp封装就完成了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值