本帖最后由 cheekhan 于 2023-4-8 14:04 编辑
0、前言
说起跨域,我们都很熟悉。尤其是在前后端分离的开发模式下,跨域问题贯穿始终,从开发联调阶段,到打版发布,都绕不开跨域问题。以下文章内容,将对工作中遇到的跨域问题,进行一下简单的总结归纳。
1、跨域
跨域这种能力,源于同源策略。
同源策略,是一种为了浏览器安全而制定的策略,可以理解为,就是只能获取同源下的数据。而同源的判定,是指的 协议+域名+端口 都一致,才是同源。
同源策略是重要的安全策略,但是某些情况,又存在获取非同源数据的需求,所以又有了跨域这种功能(注意区分跨域和同源,很多同学混淆了两个概念,把跨域当作是同源,其实跨域更应该理解为同源策略下的一个解决方案)。
所以,跨域,就是在一定的条件下,获取非同源数据的能力。
2、CORS
CORS,全称“跨域资源共享”,是一种 用于跨域的标准。目前所有浏览器均有实现。
CORS的实现,需要服务端进行一定的配合,其余过程,全部由浏览器进行实现,并不需要额外的代码。
发起一个CORS请求,如果请求方法是HEAD、GET、POST三种方法之一,且请求头只有Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type这几种,那这个请求方法就是一个简单请求;
如果有其他的请求方法、或者额外的请求头,那就是一个复杂请求了。
对于简单请求和复杂请求,浏览器和服务端都需要进行一些差异化的处理流程。
3、简单请求
简单请求的流程图,大体如下:
origin请求头,用于标识请求来源的域,后端可以进行判断,是否在白名单内,如果在白名单内就进行CORS;否则就不进行处理,浏览器会抛出CORS异常。
如果是可以响应CORS的情况,将会在响应中,添加三个响应头:
Access-Control-Allow-Origin、Access-Control-Allow-Credentials、Access-Control-Expose-Headers
Access-Control-Allow-Origin:用于标识允许跨域的源,给浏览器使用,如果和请求的origin一样,或者为*,浏览器就将请求通过,否则依然抛出CORS异常;
Access-Control-Allow-Credentials:用于标识是否能发送cookie。但是大部分浏览器的实现,都是默认会发送cookie。
Access-Control-Expose-Headers:用于暴露额外的响应头。因为跨域请求的情况下,只能拿到一些基本的响应头,可以在这里进行设置,以用来暴露更多的响应头。
更多的响应配置,可参考文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS#http_%E5%93%8D%E5%BA%94%E9%A6%96%E9%83%A8%E5%AD%97%E6%AE%B5
4、复杂请求
也叫做“需预检的请求”。
需要预检的请求,首先浏览器会发送一个请求方法为OPTIONS的请求:
当options请求返回校验通过之后,才能再次发起复杂请求,后续的复杂请求处理流程,就和简单请求的流程是一样的了。
|