跨域问题CORS笔记

CORS跨域问题

跨域问题简介

跨域资源共享(Cross-origin resource sharing, CORS)是用于让网站资源能被不同源网站访问的一种安全机制,这个机制由浏览器与服务器共同负责,浏览器在其中扮演最重要的角色。

同源

协议相同(httphttps)、域名相同、端口相同就是同源。

同源限制了B网站获取到非同源的A网站保存在浏览器的Cookie、LocalStorage、IndexDB、DOM、AJAX请求。当A网站的网页内有跨域请求且A网站后端并未添加跨域请求头,浏览器将拦截该跨域请求。

请求过程

当浏览器发出特定不安全的HTTP和Ajax请求时,CORS机制要求浏览器首先需要发送一个HTTP OPTIONS预检请求用于检查服务器是否批准来自该地址的请求并指定是否接收认证信息(例如Cookies等),浏览器将遵循服务器的限制正式请求的情况。出于安全考虑,如果跨域请求被拒绝,错误将只会返回到浏览器控制台内,JavaScript代码不会接收到错误信息。

不会触发OPTIONS预检请求的条件是:

  • 请求方法为GET、HEAD、POST
  • 请求头安全Accept、Accept-Language、Content-Language、Content-Type(仅限于text/plain、multipart/form-data、application/x-www-form-urlencoded)、DPR、Downlink、Save-Data、Viewport-Width、Width

不发出预检请求的例子

下面是一个不需要发送预检请求的从http://foo.example网站的网页或JavaScript访问http://bar.example请求的简化版,Origin请求头用于标志请求来源

GET /resources/public-data/ HTTP/1.1
Origin: http://foo.example

以下是支持CORS的http://bar.example返回内容的简化版,Access-Control-Allow-Origin头标记该网站可以被跨域访问的源,*代表可以被任意源访问,如果仅允许来自http://foo.example的请求则改为http://foo.example

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *

会发出预检请求的例子

下面是一个需要发送预检请求的从http://foo.example网站的网页或JavaScript访问http://bar.example请求的简化版,下面两个头文件内容是预检请求与其返回内容

OPTIONS /resources/post-here/ HTTP/1.1
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

下面两个头文件内容是实际请求的内容

POST /resources/post-here/ HTTP/1.1
Host: bar.other
X-PINGOTHER: pingpong
Origin: http://foo.example
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.example

身份凭证的特别处理

当同源时,浏览器请求可以带有Cookie等身份认证信息,但是如果跨源请求需要携带身份凭证,则需要为XMLHttpRequestFetch API进行额外设置。但是只要需要前端进行跨源请求时携带用户凭证,服务器设置的Access-Control-Allow-Origin就不能为*而需要设置为允许跨域请求的来源域名

跨域相关HTTP头

响应中的头

响应头内容需要在服务器端进行定义,具体定义方法需要根据后端使用语言、框架不同有所改变。

  • Access-Control-Allow-Origin: <origin http address> | *:设置允许跨域访问该资源的域名,设置为通配符*时凭证信息将不会被携带
  • Access-Control-Expose-Headers: <headers>[, <headers>]*: 设置浏览器可访问请求头的白名单,设置之后getResponseHeader()就可访问默认白名单外的请求头
  • Access-Control-Max-Age: <seconds>:指定OPTIONS预检请求最长有效时间
  • Access-Control-Allow-Credentials: true:指定当跨源身份凭证发送时浏览器是否可以读取返回内容,如果用在预检请求上,将决定浏览器在发出正式请求时是否携带有凭证,如果请求无预检请求例如GET,则该响应会被忽略且浏览器也不会将内容返回给网页
  • Access-Control-Allow-Methods: <method>[, <method>]*:指明实际请求所使用的HTTP方法
  • Access-Control-Allow-Headers: <field-name>[, <field-name>]*:指明了实际请求允许携带的首部字段

请求中的头

  • Origin: <origin>:指明了请求源站地址,不包含任何路径信息,只包含服务器名称
  • Access-Control-Request-Method: <method>:在预检请求上表明实际请求所使用的HTTP方法
  • Access-Control-Request-Headers: <field-name>[, <field-name>]*:在预检请求上表明实际所携带的首部字段
posted @ 2020-09-26 12:04  CamWang  阅读(85)  评论(0编辑  收藏  举报