CORS(跨域资源共享)
CORS:一种基于HTTP头的机制,该机制允许服务标示除了它自己以外的其他源(域、协议、端口),使得浏览器允许这些源访问加载自己的资源
对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET
以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST
请求),浏览器必须首先使用 OPTIONS
方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨源请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(例如 Cookie 和 HTTP 认证相关数据)。
若请求满足所有下述条件,则该请求可视为简单请求:
使用下列方法之一:
除了被用户代理自动设置的标头字段(例如
Connection
、User-Agent
或其他在 Fetch 规范中定义为禁用标头名称的标头),允许人为设置的字段为 Fetch 规范定义的对 CORS 安全的标头字段集合。该集合为:
Accept
Accept-Language
Content-Language
Content-Type
(需要注意额外的限制)Range
(只允许简单的范围标头值 如bytes=256-
或bytes=127-255
)
Content-Type
标头所指定的媒体类型的值仅限于下列三者之一:text/plain
multipart/form-data
application/x-www-form-urlencoded
如果请求是使用
XMLHttpRequest
对象发出的,在返回的XMLHttpRequest.upload
对象属性上没有注册任何事件监听器;也就是说,给定一个XMLHttpRequest
实例xhr
,没有调用xhr.upload.addEventListener()
,以监听该上传请求。请求中没有使用
ReadableStream
对象。
服务端返回的 Access-Control-Allow-Origin
标头的 Access-Control-Allow-Origin: *
值表明,该资源可以被任意外源访问。
Access-Control-Allow-Origin: * |
当响应的是附带身份凭证的请求时,服务端必须明确 Access-Control-Allow-Origin
的值,而不能使用通配符“*
”
预检请求
与简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS
方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。”预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响
下面是服务端和客户端完整的信息交互。首次交互是预检请求/响应:
OPTIONS /doc |
在响应附带身份凭证的请求时:
- 服务器不能将
Access-Control-Allow-Origin
的值设为通配符“*
”,而应将其设置为特定的域,如:Access-Control-Allow-Origin: https://example.com
。 - 服务器不能将
Access-Control-Allow-Headers
的值设为通配符“*
”,而应将其设置为标头名称的列表,如:Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
- 服务器不能将
Access-Control-Allow-Methods
的值设为通配符“*
”,而应将其设置为特定请求方法名称的列表,如:Access-Control-Allow-Methods: POST, GET
Http响应标头字段
Access-Control-Allow-Origin
Access-Control-Allow-Origin: <origin> | * |
该字段的值为通配符“*
”,表示允许来自任意源的请求
如果服务端指定了具体的单个源(作为允许列表的一部分,可能会根据请求的来源而动态改变)而非通配符“*
”,那么响应标头中的 Vary
字段的值必须包含 Origin
。这将告诉客户端:服务器对不同的 Origin
返回不同的内容。
Access-Control-Allow-Origin: https://mozilla.org |
Access-Control-Expose-Headers
跨源访问时,XMLHttpRequest
对象的 getResponseHeader()
方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头。
Access-Control-Expose-Headers: <header-name>[, <header-name>]* |
Access-Control-Allow-Credentials
头指定了当浏览器的 credentials
设置为 true 时是否允许浏览器读取 response 的内容。当用在对 preflight 预检测请求的响应中时,它指定了实际的请求是否可以使用 credentials
。请注意:简单 GET
请求不会被预检;如果对此类请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页。
Access-Control-Allow-Credentials: true |
Access-Control-Allow-Methods
Access-Control-Allow-Methods
标头字段指定了访问资源时允许使用的请求方法,用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。
Access-Control-Allow-Methods: <method>[, <method>]* |
Access-Control-Allow-Headers
Access-Control-Allow-Headers
标头字段用于预检请求的响应。其指明了实际请求中允许携带的标头字段。这个标头是服务器端对浏览器端 Access-Control-Request-Headers
标头的响应。
Access-Control-Allow-Headers: <header-name>[, <header-name>]* |
Http请求标头字段
Origin
Origin
标头字段表明预检请求或实际跨源请求的源站。
Origin: <origin> |
Access-Control-Request-Method
Access-Control-Request-Method
标头字段用于预检请求。其作用是,将实际请求所使用的 HTTP 方法告诉服务器。
Access-Control-Request-Method: <method> |
Access-Control-Request-Header
Access-Control-Request-Headers
标头字段用于预检请求。其作用是,将实际请求所携带的标头字段(通过 setRequestHeader()
等设置的)告诉服务器。这个浏览器端标头将由互补的服务器端标头 Access-Control-Allow-Headers
回答。
Access-Control-Request-Headers: <field-name>[, <field-name>]* |