同源策略
同源策略是一种约定,指的是协议、域名和端口三者相同,它是浏览器最核心也是最基本的安全功能。缺少这个功能,
就容易受到XSS、CSRF的攻击。
同源策略的限制内容:
(一)Cookies、LocalStrange、IndexedDB等存储性的内容。
(二)DOM节点。
(三)AJAX请求发送后,结果被浏览器拦截。
JSONP
原理
三个标签允许跨域:img标签、link标签、script标签,JSONP就是利用script的这个特性进行跨域。
实现步骤
(一)声明一个回调函数,其函数值作为参数值,要传递给跨域请求数据的服务器,函数的形式参数为服务器返回的数据。
(二)创建一个script标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名。通常使用?传递参数
(三)服务器接受请求,对数据进行拼接处理。
(四)服务器通过HTTP协议把数据返回给客户端,客户端再调用之前的回调函数。
用于测试的服务端
//1、引入模块 使用的http服务协议是RFC2616 nodejs的作者已经写好了,直接引入就行
var http = require('http');
var querystring = require('querystring');
//引入文件读写模块fs
var fs = require('fs');
//2、创建服务器 函数的参数req是发送给服务器的请求,res是服务器的相应
var httpObj = http.createServer(function (req, res) {
var qs = querystring.parse(req.url.split('?')[1]);
res.writeHead(200, { 'Content-Type': 'application/json;charset=utf-8' });
var data = "Monkey"
var callback = qs.callback + '(' + JSON.stringify(data) + ')';
res.end(callback);
});
//监听端口
httpObj.listen(3000);
JSONP的实现
首先实现一个最简单的JSOP;
function jsonp(url){
const script=document.createElement("script");
script.src=url;
script.type="type/javascript";
document.body.appendChild(script);
}
这个只是最基本的写法,要是想要使用需要定义全局的回调函数,这样是不可取的。
接下来,进行改进:
function jsonp({url,params,callback}){
window[callback]=callback;
const script=document.createElement("script");
let arr=[];
params={...params,callback};
for(var key in params){
arr.push(`${key}=${params[key]}`);
}
script.src = `${url}?${arrs.join('&')}`;
script.type="type/javascript";
document.body.appendChild(script);
}
这个函数改进了上面的不足,但是还有很多的不足:
(1)没有清楚生成的script标签。
(2)要写回调,写法麻烦。
下面使用es6的promise进行改进:
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
window[callback] = (data) => {
resolve(data);
document.body.removeChild(script);//删除了script标签
}
params = { ...params, callback };
let arrs = [];
for (let key in params) {
arrs.push(`${key}=${params[key]}`);
}
script.src = `${url}?${arrs.join('&')}`;
script.type="type/javascript";
document.body.appendChild(script);
});
}
jsonp({
url: 'http://localhost:3000/',
params: { test: 'test' },
callback: 'show'
}).then((data) => {
console.log(data);
}).catch((e) => { console.log(e) })
上面已经通过es6实现了JSONP,但是是否觉得有什么不对劲的地方,没错,就是缺少了错误处理。
最后的改进:
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
window[callback] = (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('&')}`;
script.type="type/javascript";
document.body.appendChild(script);
script.onerror = () => {
reject(new Error(`fetch ${url} failed`));
document.body.removeChild(script);
}
});
}
jsonp({
url: 'http://localhost:3001/',
params: { test: 'test' },
callback: 'show'
}).then((data) => {
console.log(data);
}).catch((e) => { console.log(e) })
jsonp({
url: 'http://localhost:3000/',
params: { test: 'test' },
callback: 'show'
}).then((data) => {
console.log(data);
}).catch((e) => { console.log(e) })
说在最后
小菜鸡大三下了,希望找实习了,有一起找实习的小伙伴私信我吧,一起努力吧。
最后不要脸的说一句:github求star("https://github.com/changchangge").
网友评论