前端跨域致命连环问
在面试的时候,面试官问了我一个问题:“你知道如何实现跨域吗?”
我点了点头,心中不屑,随后答道:
跨域是由于浏览器的同源策略所导致的,浏览器的同源策略是指只有“协议、域名、端口”相同我们才能进行通信,当有一个不满足的时候,我们就无法进行跨域。
现在常见的一些手段比如:“JSONP、CORS、WEBPACK配置”
JSONP
然后第二问题来了:“那你知道 JSONP 是如何实现的吗?”
我皱眉思索了一阵:“这是一种民间的解决方案,应该是利用了 script 标签不受浏览器的同源策略影响的性质来做的,当然还需要前后端的配合。”
“那你知道前后端具体是怎么配合的吗?”
我愣了一下,还要这么细么????
后来回去查了一下,我们可以这么做
- 客户端事先准备一个接收数据的全局函数
- 客户端解析道外联的Script标签,发出请求
- 服务端收到请求,返回函数的调用
- 客户端收到数据,执行回调。
代码嘛,可以看下面的:
- 在发请求前,准备一个全局的接收函数
window.myCallback = (res) => {
console.log(res)
}
- 在 html 创建 script 标签,发出请求
<html>
....
<script>
window.myCallback = (res)=>{ //这里为上一步定义的全局函数
console.log(res)
}
</script>
<script url="xxx?callback=myCallback">
//script标签的请求必须在写在定义全局函数之后
//这里需将全局函数的函数名作为参数callback的value传递
//这里callback这个键名是前后端约定好的
</script>
</body>
</html>
- 服务端接收到请求,将如下数据返回
myCallback({
name: 'ahreal',
age: 18,
})
- 客户端接收到服务端的相应,相当于:
<html>
....
<script>
window.myCallback = (res)=>{ //这里为上一步定义的全局函数
console.log(res)
}
</script>
<script> //将接收到的数据作为script标签里面的内容展开执行
myCallback({
name:'ahreal',
age:18
})
</script>
</body>
</html>
CORS
面试官看我 JSONP 蒙住了,就转头来问我 CORS。
那你知道 CORS 一般咋使用吗?
知道啊,我们可以配置 Access-Control-Allow-Origin
来选择我们允许跨域的域名,如果前端请求之后返回值带有 Access-Control-Allow-xxx
那多半是可以进行跨域请求;对于复杂请求呢,我们需要发送一个预检请求,需要携带 Access-Control-Request-Method & Access-Control-Request-Headers
,如果返回值有 Access-Control-Allow-xxx
那就应该是可以。
嗯嗯,那你知道如何给 CORS 设置 Cookie 吗?
What???
这又是个啥,之前没见过啊。
明说不会,这一 Part 才结束。
下来查了一下是怎么回事:
在
CORS
请求中,如果想要传递Cookie
,就要满足以下三个条件:
- 在请求中设置
withCredentials
为true
该属性是一个
Boolean
类型,当异步对象设置了WithCredentials=true
时,浏览器会保留下响应的Cookie
等信息,并且下次发送请求时将其携带。
var xhr = new HMLHttpRequest();
xhr.withCredentials = true;
axios.default.withCredentials = true;
- 在响应头设置:
Access-Control-Allow-Credentials
设置为true
Access-Control-Allow-Credentials
该头是可选的,是一个bool
值,它若为true
就有两个作用:
在跨域请求的响应中允许
Set-Cookie
响应头浏览器收到响应后,浏览器根据此头判断是否让自己的
withCredentials
属性生效
- 在响应头中设置:
Access-Control-Allow-Origin
设置为非*
服务端的
Access-Control-Allow-Origin
设置为非 *
服务端的
Access-Control-Allow-Origin
这个响应头的值不能说通配符*
,而只能是具体的值,否则会出现报错。
那么这就是本篇文章的全部内容了
点个赞再走吧~
转载自:https://juejin.cn/post/7208885488801988668