跨域(二)CORS

CORS跨域是目前使用最多的跨域解决方案,是W3C的一种技术规范,2014年起成为行业的标准,当前所有的浏览器都支持CORS。属于HTTP的一部分。

CORS(Cross-origin resource sharing):跨域资源共享。要实现CORS需要前后端同时的支持,而浏览器自动给支持CORS,所以设置主要是服务器端。

浏览器将CORS请求分为两种:简单请求和非简单请求。
简单请求(同时满足两大条件):
(1)请求方法是以下三种之一:
HEAD
GET
POST
(2)Http的头信息不超出以下几种字段
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

除了上述情况,其他的都属于非简单请求。两个条件是为了兼容表单(form),表单一直可以发出跨域请求,ajax只要表单可以发,它就可以直接发,表单不能发的,通过预检判断是否可以发送。

在这里插入图片描述
对于简单请求:浏览器直接将请求发送到服务端,服务端返回响应。浏览器会从响应中判断是否可以跨域,如果可以跨域,则进行正常处理,如果不能跨域,浏览器报错。

对于非简单请求:浏览器会先发送一个预检请求(preflight),在Http中就是OPTIONS请求方式。预检请求不包含主体(没有请求参数和请求体),将一些凭证、授权相关的辅助信息放在请求头中,询问服务器所在网页是否在服务器的许可名单内,以及可以使用那些Http方法和头信息字段。如果不能跨域,则实际请求不会发送并报错,如果可以跨域则发送后续请求,进行处理。

CORS相关头:

浏览器如果发送跨域请求,在http请求中就会携带一个名为Origin的头。
在这里插入图片描述
Host:目标地址
Origin:来自那里 协议+端口+域名 即判断是否同源的三要素
Referer:来自那里 协议+端口+域名+路径+参数

Referer比Origin多了路径和参数,功能类似。Orgin用于CORS请求,而Referer则被用来进行统计分析、日志记录和缓存优化等。

Origin只有跨域请求或者同于POST请求才会带上,其他情况没有Origin头,而Referer只要浏览器能获取都会携带。

浏览器获取不到请求源页面地址,Referer不会发送,但是Origin为null。

浏览器在发送简单跨域请求会带上Origin,如果发送非简单跨域请求,还会添加两个特殊字段。

Access-Control-Request-Method(必须):列出浏览器的请求会用到那些方法
Access-Control-Request-Headers(可选):指定浏览器CORS请求会额外发送的头信息字段,当使用了简单请求中5个字段之外的字段,会在OPTIONS请求头域中,执行Access-Control-Request-Headers取值。

浏览器在接受到服务器返回响应后,会从中提取相应的CORS字段进行判断。这些字段实在服务器中设置的,如果有则发回设置值,如果没有就不发。

如果是简单请求, 可能包含:
Access-Control-Allow-Origin(必选)
Access-Control-Allow-Credentials(可选)
Access-Control-Expose-Headers(可选)

如果是非简单请求,可能包含:
Access-Control-Allow-Origin(必选)
Access-Control-Allow-Credentials(可选)
Access-Control-Expose-Headers(可选)
Access-Control-Max-Age(可选)
Access-Control-Allow-Method(必选)
Access-Control-Allow-Headers(可选)

非简单请求的响应多了Access-Control-Allow-Method和Access-Control-Allow-Headers,是对非简单请求的头字段Access-Control-Request-Method和Access-Control-Request-Headers的回复。Access-Control-Max-Age表示预检请求的有效时间,在时间段内不需要再次预检请求。

Access-Control-Allow-Origin:允许的域名,只能填 *(允许任意域名)或者单域名

Access-Control-Allow-Credentials:表示是否允许发送Cookie,只有一个可选值:true(必为小写)。如果不包含cookies,请略去该项,而不是填写false。这一项与 XmlHttpRequest 对象当中的 withCredentials 属性应保持一致,即 withCredentials 为true时该项也为true;withCredentials 为false时,省略该项不写。二者必须同时设置才会起作用

当启用Access-Control-Allow-Credentials时,Access-Control-Allow-Origin不能为*。因为假设用户登录网站A后进入网站B,网站B拿着网站A的cookie登录网站A,如果网站A设置的Access-Control-Allow-Origin为任意域名,那么此时登录成功,用户数据泄露。CSRF

Access-Control-Expose-Headers:CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

Access-Control-Max-Age:用来指定本次预检请求的有效期,单位为秒。例如,Access-Control-Max-Age被设置为1728000,表示有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求

Access-Control-Allow-Method:允许跨域请求的 http 方法(如POST、GET、OPTIONS、PUT、DELETE),该字段是对于预检请求中的Access-Control-Request-Method的回复。

Access-Control-Allow-Headers:该字段指定了跨域允许设置的非简单Http请求头(5个简单Http请求头之外的头域),(当预请求中包含 Access-Control-Request-Headers 时必须包含)– 这是对预请求当中 Access-Control-Request-Headers 的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。

普通请求的,是浏览器先将请求发出(请求头有Origin),服务器响应后发回浏览器,浏览器从响应头中提取上述字段(Access-Control-Allow-Origin等),如果返回的Origin为 * 或者与当前同域,则表示允许跨域。如果Origin不是任意或者与当前不同域,浏览器报错,响应不给前端展示。当服务器不设置Access-Control-Allow-Origin,响应头不会包含Origin,浏览器报错并且不展示响应。

当XmlHttpRequest中设置了withCredentials为true,如果服务器响应里没有Access-Control-Allow-Credentials字段,则浏览器会报错。

如果在服务器响应中,没有携带Access-Control-Expose-Headers或者Access-Control-Expose-Headers的值不包含所期望的值,则浏览器会报错。

Access-Control-Allow-Methods:允许跨域请求的 http 方法(如POST、GET、OPTIONS、PUT、DELETE),如果响应中不包含跨域所需要的方法,浏览器报错。

Access-Control-Allow-Headers:该字段指定了跨域允许设置的非简单Http请求头(5个简单Http请求头之外的头域),(当预请求中包含 Access-Control-Request-Headers 时必须包含)– 这是对预请求当中 Access-Control-Request-Headers 的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。

Access-Control-Allow-Headers的值自动包含Access-Control-Expose-Headers。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值