OPTION为跨域请求准备

OPTION为跨域请求准备

先学习一下同源策略和跨域资源共享

同源策略

如果两个URL协议(protocol)、端口(port)、主机(host),都相同,则称这个URL为同源。CORS它是W3C万维网联盟的标准,它定义了在跨域访问资源时浏览器和服务器之间如何通信。它是为突破同源策略的限制而出现的一种官方标准的跨域解决方案。在实战场景中,跨域场景太为常见了(特别是当下前后端分离的开发模式),因此深入理解CORS变得就异常的重要了(反倒前端工程师不用太了解)。

以http://music.javaswing.cn/home/index.html

URL结果原因
http://music.javaswing.cn/static/other.html 同源
http://music.javaswng.cn/inner/start.html 同源
http://music.javaswing.cn:8000/other.html 不同源端口不同
https://music.javaswing.cn/inner/start.html 不同源协议不同
http://api.javaswing.cn/start.html 不同源主机不同

作用:同源策略的存在,主要是为用于限制文档与它加载的脚本如何能与另一个资源进行交互,为重要的安全策略。

比如:你本地http://localhost:3000的项目访问http://localhost:8000的项目,就会出现:has been blocked by CORS policy

Access to XMLHttpRequest at ‘http://localhost:3000/’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

CORS

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。

简单的来说:CORS就是两种在不同的域、协议或端口(即不在同源中),服务之间能相互访问。

OPTION请求

在CORS机制一个域名A要访问域名B的服务,在一些特殊的复杂请求下(简单请求并不会进行预请求),浏览器必须先使用OPTIONS请求进行一个预检请求(preflight request)来获取B服务是否允许跨域请求,服务进行确认之后,才会发起真正的HTTP请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

简单请求有以下几种:GET、HEAD、POST

  1. HTTP的头信息不超出以下几种字段:
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (需要注意额外的限制)
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width
  1. Content-Type 的值仅限于下列三者之一:
  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

如何优化

如果不想让每个CORS复杂请求都出两次请求,可以设置Access-Control-Max-Age这个属性。让浏览器缓存,在缓存的有效期内,所有options请求都不会发送。优化性能。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
app.use(async (ctx, next) => {
    // 允许来息所有域名的请求
    ctx.set('Access-Control-Allow-Origin', '*')

    // 允许HTTP请求的方法
    ctx.set('Access-Control-Allow-Methods', 'OPTIONS,DELETE,GET,PUT,POST')

    // 表明服务器支持所有头信息字段
    ctx.set('Access-Control-Allow-Headers', 'x-requested-with, accept, origin, content-type, token')

    // 设置请求preflight缓存的时间,单位 秒
    ctx.set('Access-Control-Max-Age', 10)
    })

总结

在当前,前后端分离的开发模式下,跨域问题是经常遇到的,OPTIONS只不过CORS机制当中的一个预检测请求。而且这个请求是整个CORS机制控制的,并不能在前端用代码进行控制。主要作用:

  1. 检测服务器支持的请求方法
  2. CORS 中的预检请求

细节代码学习请看:

CORS跨域资源共享(一):模拟跨域请求以及结果分析,理解同源策略【享学Spring MVC】