小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
问题引入
想必大家在与后端同学联调接口时,经常会遇到以下报错:
这报错是浏览器跨域引起的报错,那跨域到底是什么呢?
什么是跨域
在这里,引入了一个概念:同源策略
意思是说,如果协议,域名或者端口都相同才满足同源策略,资源之间才能互相访问。
http://baidu.com:8000/test
该条链接可知协议是http,域名是baidu.com,端口是8000
如果有其中一个条件不符合,就会引起跨域问题,比如
- http协议不一致
http://baidu.com 和 https://baidu.com
- 域名不一致
http://baidu.com 和 http://google.com
- 端口不一致
http://baidu.com:8000/test 和 http://baidu.com:8001/test
跨域问题是不满足同源策略引起的,那么为什么浏览器要引入这个同源策略呢?
同源策略引入原因
浏览器引入同源策略是为了防止CSRF攻击,CSRF攻击是利用用户的登录态发起恶意请求。
假如有A和B两个站点,在没有同源策略的情况下,A和B是可以互相访问的。如果A站点已经登录,存在登录状态,那么B站点就可以通过访问A站点获取到A站点的登录信息,从而发起恶意请求。
既然有了同源策略,浏览器是怎么拦截的呢?
跨域在何处被拦截
如果请求被跨域了,那么浏览器是否有发出请求?服务器是否有接到请求?实际上,请求是已经发出去了,但是浏览器在接受请求时,认为内容不安全,从而拦截了请求。
因此,你会发现,浏览器调用某接口报跨域错误,但是直接用postman工具去调接口,是可以拿到数据的,是正常的。
既然有跨域,前后端如何协助呢?
跨域处理方案
1. JSONP
jsonp的原理是利用
<script src="http://test.com/api?callback=jsonp"
<script>
function jsonp(data) {
console.log(data)
}
</script>
// http://test.com/api?callback=jsonp
jsonp('test')
JSONP的兼容性良好,但是只限于get请求。
2. Proxy
由于跨域问题是浏览器引起的,而Proxy方案通过避开浏览器来解决跨域。
我们再使用vue项目进行开发时,可以在配置里启动代理。实际vue项目会在本地启动一个node代理服务器,发起请求会先请求到node代理服务器,node代理服务器会转发请求到目标服务器。由于node代理服务器和站点 是符合同源策略的,就不会出现跨域问题。
在线上部署时,我们也可以通过添加一层代理服务器做转发来处理跨域。
3. CORS
这个方案是常用,也是我推荐的。
CORS是需要后端支持的,只要在返回响应头时,服务器设置Access-Control-Allow-Origin,那么浏览器就允许跨域。这个属性表示哪些域名可以访问,我们可以设置通配符*来使得所有站点都可以访问。
通过CORS方案来解决跨域时,浏览器在发送请求时,会分为简单请求和复杂请求。
简单请求
满足一下条件时,就会触发简单请求
- 请求方法为以下:
- GET
- HEAD
- POST
- Content-type的值为以下;
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
复杂请求
不是简单请求的就是复杂请求。
对于复杂请求,浏览器会先发起一个预检查请求,为OPTION方法,用来咨询服务器是否支持跨域。
如果服务器返回200,表示支持跨域,那么浏览器才会发送真正的请求。因此服务器需要处理OPTION请求。
4. 浏览器插件
插件地址:chrome.google.com/webstore/de…
Chrome浏览器安装该插件后,可以避免跨域问题,具体原理是对响应头设置跨域头,和CORS一样,但不是服务器设置,而是插件设置。
这个方法只能用在开发环境上,便于开发人员调试。
总结
以上就是我对浏览器跨域的理解,如果觉得对你有帮助,请帮忙点个赞+评论+收藏。