C O R S
所有前端工程师都知道跨域问题(不同的协议、域、端口),也都知道解决跨域的常见方式是通过设置cors。 那么cors到底是什么,它是如何解决跨域问题的呢
CORS全称Cross-Origin Resource Sharing,即跨域资源共享。是解决跨域问题常见的方式。
简单请求和非简单请求
满足以下条件即视为简单请求
-
请求方法为以下任意方法之一(在W3C规范中也称为简单方法 simple method)
- GET
- HEAD
- POST
-
请求头只能包含以下字段 (在W3C规范中前4种称为简单头部 simple header,不包括浏览器自动设置的那些,比如User-Agent,Connection等)
- Accept
- Accept-Language
- Content-Language
- Content-Type (仅支持 application/x-www-form-urlencoded 、multipart/form-data 、text/plain)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- 请求中的XMLHttpRequestUpload对象没有注册事件监听
- 请求中没有使用 ReadableStream 对象。
对于简单请求,浏览器会直接发起实际跨域请求,只要返回头部中设置了正确的Access-Control-Allow-Origin
字段即可成功请求,否则你会在浏览器的console
面板看到类似于下面这样报错
Access to XMLHttpRequest at 'http://domain.com/api/test' from origin 'http://localhost:1234' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
对于非简单请求,在发起实际的请求之前,浏览器会发起一个预检请求(preflight request),这是个options请求,包含以下字段
- Access-Control-Request-Method (表示实际发生的请求方法)
- Access-Control-Request-Headers (如果实际的请求头部不为空,则会将实际的请求头部中用到的字段放入该字段中)
- Origin (表示请求来源)
当预检请求通过后,才会发起真实的请求,否则你会在浏览器的console
面板看到类似于下面这样报错(这里是请求头没有通过预检)
Access to XMLHttpRequest at 'http://domain.com/api/test' from origin 'http://localhost:1234' has been blocked by CORS policy: Request header field custom-header is not allowed by Access-Control-Allow-Headers in preflight response.
另外,需要同时对接口的options
方法以及真实的get
或post
方法设置对应的返回头。如果只设置了真实请求方法的返回头,而没有相应设置options方法的返回头,预检也不会通过。你会在浏览器的console
面板看到类似于下面这样报错
Access to XMLHttpRequest at 'http://domain.com/api/test' from origin 'http://localhost:1234' 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.
并非所有非简单方法都会发起预检请求
预检请求是有缓存的!在预检请求的返回头中设置Access-Control-Max-Age
字段,值为int类型,代表过期时间,单位是秒。 在该时间段之内,非简单方法发送跨域请求不会再事先发起预检请求。
response header
对于预检请求,可以返回下列字段
- Access-Control-Allow-Origin (允许的域)
- Access-Control-Allow-Method (允许的请求方法,简单请求可不列出,也就是说即使你只设置了POST,GET方法也是会通过的)
- Access-Control-Allow-Headers (允许的请求头部)
- Access-Control-Max-Age (缓存时间,上面已经介绍过了)
- Access-Control-Allow-Credentials(是否允许携带用户认证信息 cookie , HTTP authentication等,当该值为true时,
Access-Control-Allow-Origin
不能为*
,当该值为false,同时请求又携带了credentials,该请求的返回会被浏览器忽略) - Access-Control-Expose-Headers (可以暴露给浏览器的头部)
本文主要知识来源并推荐阅读:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。