序言
我们今天学习的重点是 JSONP 的实现原理,JSONP( Json with padding ) , 是解决跨域问题的一种方法,所以这篇文章会简单的介绍一下跨域相关的问题,然后重点理解一下 JSONP 方法的原理。
什么是跨域
说到跨域,就要了解一下同源政策了,同源政策是一张约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS、CSRF 等攻击。所谓同源是指”协议 + 域名 + 端口”三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源。
我们可知,一个域名地址有5个组成部分,只有当 **协议 **,子域名, 主域名,端口 都相同的时候,才算同域,可以互相请求资源,但凡有一个不相同都产生了跨域,都会被同源政策限制相互通信。
小提示:
如果是犹豫协议和端口造成的跨域问题,前端是无能为力的。
利用JSONP解决跨域
在 html 标签中,有三个标签是允许跨域加载资源的。
<img src="https://juejin.cn/post/xxx">
<link href="https://juejin.cn/post/xxx">
<script src="https://juejin.cn/post/xxx">
JSONP原理
利用<script>
标签没有跨域限制的性质,网页可以得到其他源产生的 JSON 数据,为什么不用<img>
<link>
呢,因为只有 script
标签可以指定 Content-Type : text/javaScript
,其他返回的只有数据,而不是脚本,并不会执行。
JSONP实现代码
前端部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
<script>
// index.html
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) => {
let script = document.createElement("script");
window[callback] = function (data) {
resolve(data);
document.body.removeChild(script);
};
params = { ...params, callback }; //
let arrs = [];
for (let key in params) {
arrs.push(`${key}=${params[key]}`);
}
script.src = `${url}?${arrs.join("&")}`;
console.log(script.src);
document.body.appendChild(script);
});
}
jsonp({
url: "http://localhost:3000/index",
params: { params: "我是coolFish" },
callback: "callback",
}).then((data) => {
console.log(data);
});
</script>
</html>
复制代码
我们发送的请求为[http://localhost:3000/index?params=coolFish&callback=callback](http://localhost:3000/index?params=coolFish&callback=callback)
我们可以看到参数和回调函数,在 url 上携带,服务器拿到以后,将回调函数作为脚本传回前端,前端接收到了,就会执行 callback 函数。这样我们就通过 callback 函数的参数,拿到了我们想要的数据。
用 express 起一个服务器模拟服务端
首先安装依赖
npm install express --save-dev
运行
node index.js
实现代码:创建了一个地址 [http://localhost:3000/index](http://localhost:3000/index)
const express = require("express");
const app = express();
app.get("/index", (req, res) => {
let { params, callback } = req.query;
console.log(params); // coolFish
console.log(callback); // callback
res.send(`${callback}('我是郭老师')`);
}),
app.listen(3000, () => {
console.log("服务开启成功了"); //yellow
});
复制代码
我们在浏览器的控制台可以接受到服务器传来的消息。
这就我们就简单的实现了一个 JSONP 解决跨域的方案。
JSONP的优缺点
优点:
- 兼容性好,操作简单。
缺点:
- 仅仅只支持 get 请求。
- get 请求携带参数受限,大小 4kb 左右。
- 不够安全,可能会遭受 xss 攻击。
总结:
- 首先理解什么是同源政策,什么是跨域。
- JSONP 解决跨域的数据交流主要是借助了
<script>
标签不受同源政策的影响。 <img>
和<link>
也不受同源政策影响,但是它接收不到服务端的数据。