好久没有更新博客了,前段时间在疯狂面试,最近工作了才有时间来写博客。
准备来讲讲面试里常问到的跨域处理吧。
说到跨域,我们可能会下意思的说出jsonp,服务端配置cors,node配置代理等,再多了,我可能想不起来了。本篇本来打算只记录postMessage这种方式的,但光说这个显得太单薄了,所以一并都总结一下吧。
跨域是什么,为什么会跨域?
要想知道为什么,你得先知道什么是同源策略。同源策略是浏览器的一个安全协议(否则都乱套了,大家都能随意访问对方的数据,都在裸奔,也就没有隐私而言了),它限制了只有在同源的情况下才可以安全访问请求到数据,同源即同一个协议、域名、端口即是同源,比如:
http://localhost:8000
这里http就是协议
localhost是域名
而8000就是端口
协议域名端口哪怕有一个不同,都会造成跨域导致无法正常去请求。但我们在日常开发的时候,早已经前后端分离了,所以在联调接口的时候,就会有各种跨域问题。
JSONP
在那个用jq刀耕火种的那个年代,jq就基于xmlHttprequest封装了ajax请求库,在请求配置项里可以直接配置jsonp:true
来做跨域请求。原理是利用script标签加载不受跨域的影响,将请求放到script标签的src属性上。同时声明一个回调函数用于接收数据,在请求后面加上这个回调函数,服务端接收到请求后把参数放到回调函数里,本次http连接结束后会自动执行这个回调函数。通过这种方式,我们实现了跨域请求。
上才艺
function jsonp(src) {
const script = document.createElement("script");
script.src = `${src}?callback=onSuccess`;
document.head.appendChild(script);
script.onload = () => {
// 加载成功后自动删除该标签
document.head.removeChild(script)
}
}
同时声明一个onSuccess
函数用于响应请求接收结果
function onSuccess(res) {
console.log(res);
}
以上:我们声明了一个jsonp函数用于跨域请求数据,并声明一个onSuccess
函数用于接收请求数据;
服务端响应(这里以node为例)
随便拉个脚手架搭个node服务,创建一个路由用于测试jsonp跨域请求。
search.get('/test', async ctx => {
const cb = ctx.query.callback;
const result = {
code: 0,
data: {
name: 'xxxxxx',
token: 'xxxxxxxxxxxxxxx'
}
}
ctx.body = `${cb}(${JSON.stringify(result)})`
})
获取请求里的callback参数,把结果放到这个callback方法里;
前端触发jsonp这个方法去请求/search/test 看看结果
可以看到已经可以成功请求到数据了。至此,通过jsonp方法来跨域我们已经了解了。但是一定要知道这种方式的弊端,为何我们现在都不用Jsonp来做跨域请求了呢?
jsonp它只支持get请求,因为浏览器加载script脚本是通过get方式来请求的,所以没法用post请求了。众所周知的是get和post的区别里 有一条特别重要的是get会直接把请求参数拼接到连接上,相对post来说这是不够安全的。
CORS
服务端通过配置请求头,允许所有的跨域请求;
这里还是以node服务为例,比如Koa库,我们建一个中间件用于处理跨域请求;
app.use(async (ctx, next)=> {
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
if (ctx.method == 'OPTIONS') {
ctx.body = 200;
} else {
await next();
}
});
在koa实例里use这个middleware
这里主要是配置了Access-Control-Allow-Origin 允许了所有请求都能访问;
关于Access-Control-Allow-Origin的解释看mdn
node代理
明天再更其他的吧