CORS与Options相关

关于跨域

跨域概念

同域(同源)策略:相同协议、域名、端口号的url属于同源的,反之属于跨源。

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。
例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。

所有不同域之间的访问XMLHttpRequest都要解决跨域问题;无论简单请求还是复杂请求。

在浏览器端发起XMLHttpRequest调用有跨域问题,在服务器端发起调用无跨域问题。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。只需服务端做相应配置。
即客户端发起XMLHttpRequest,浏览器就会检测是否跨域,若跨域,则自动添加相应headers信息。

解决跨域的方法

通用方法:CORS。
方法1:CORS,通过添加CORS相关headers信息解决跨域。
详见“CORS方法解决跨域”。

方法2:将请求代理到服务端,在服务端发起。
如webpack/vue-cli中设置proxy信息,反向代理到指定域名。
如:

proxy: {
      '^/bpm/api': {
        target: 'http://b.com',
        ...
      },
      ...
}

即会在request url 包含 ‘/bpm/api’ 时走这个代理。访问http://localhost:8000/bpm/api会代理请求到http://b.com/bpm/api。

注:此时浏览器的Network中显示的是http://localhost:8000

方法3:nginx,在nginx上配置域名映射规则,反向代理到指定域名。
如在nginx配置的映射规则为:
‘/v1’: ‘http://b.com’,
则发送request请求时,访问/v1就会经过nginx代理转发到http://b.com。

注:此时浏览器的Network中显示的是http://localhost:8000

方法4:window.name属性、H5的postMessage属性、script标签跨域性、img标签跨域性。(都是简单请求,故无options)

方法5:JSONP方式
只支持GET请求,可以在不支持CORS时使用。

CORS方法解决跨域

该方法就是通过设置指定headers来让客户端/服务端完成信任交互。

http://a.com 请求http://b.com资源,则为跨域访问。

简单请求时:
Request Headers中设置 — Origin: http://a.com
Response Headers中设置 — Access-Control-Allow-Origin: *

非简单请求时:
Options请求 + 实际请求,
两次请求都要有 Origin/Access-Control-Allow-Origin 对的设置。

跨域请求时的cookie信息

对于跨域请求,浏览器不会发送凭证信息(cookies),如要发送,需设置headers。

Request Headers中设置 —
withCredentials: true
这样设置,浏览器端会在请求中发送cookie信息。

Response Headers中设置 —
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://a.com (不能为*)
这样设置,浏览器才会把响应数据返回给数据,否则,浏览器不会返数据给用户。

关于Options

作用:"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

是否发送预检请求(Options,HTTP/1.1中方法)前提是:
1、在跨域情况下(有Options的作用决定了在非跨域下没必要),
2、然后由简单请求和非简单请求(见附录)区分。这是浏览器自己检测后发起的。

只有非简单请求才会发送Options请求。这是由浏览器通过判断是否满足简单请求条件,来自动发起的操作。
GET、POST、HEAD不是简单请求的充分条件,必须还得满足其它条件,如首部字段设置、Content-Type等限制规范。一旦不满足任一条件,则为非简单请求。

Options请求中要有如下headers的设置

Request Headers中设置 —
Access-Control-Request-Methods: POST
Access-Control-Request-Headers: Custom-Header
这样设置是为了告诉服务端,实际会发一个POST请求,并且有一个自定义请求头Custom-Header,以便服务端验证。

Response Headers中设置 —
Access-Control-Allow-Methods: POST, OPTIONS, GET
Access-Control-Allow-Headers: Custom-Header
Access-Allow-Max-Age: 86400
这样设置是为了告诉客户端,服务端允许接下来的实际请求用的Methods和自定义头。这样浏览器才能继续发送实际请求。

上面Access-Allow-Max-Age是告诉浏览器该Options请求响应的最大有效时间,在这个时间 min(该时间, 浏览器中默认时间)内,浏览器不用发重复Options请求。

附录

简单请求和非简单请求(预检请求)

简单请求

某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。

若请求满足所有下述条件,则该请求可视为“简单请求”:

1、使用下列方法之一:
GET
HEAD
POST
2、Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为:
Accept
Accept-Language
Content-Language
Content-Type (需要注意额外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type 的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
3、请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
4、请求中没有使用 ReadableStream 对象。

违背上述 4点中任意一点,均不是简单请求了。例如一个GET请求,如果有自定义request headers的话,就不是简单请求。

非简单请求

不满足简单请求的都视为非简单请求。

与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

当请求满足下述任一条件时,即应首先发送预检请求:

1、使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
2、人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
Accept
Accept-Language
Content-Language
Content-Type (需要注意额外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Width
3、Content-Type 的值不属于下列之一:
application/x-www-form-urlencoded
multipart/form-data
text/plain
4、请求中的XMLHttpRequestUpload 对象注册了任意多个事件监听器。
5、请求中使用了ReadableStream对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值