功能概述

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

    • 避免用户访问恶意网站时,恶意网站向攻击站点发起请求并携带保存在缓存中的用户信息。即同源策略限制了1、不同源禁止访问缓存 2、不同源禁止发起请求。但存在着例外的情况,需要绕开这些限制所以出现了CORS。通过服务器的响应头来为信任的域名开放访问当前服务器资源的权限
  • 跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
  • 规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法,浏览器必须首先使用 OPTIONS 方法发起一个预检请求,从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求
    • 对服务器数据产生副作用的 HTTP 请求方法(是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求)
    • 在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。
  • CORS请求失败会产生错误,但是为了安全,在JavaScript代码层面是无法获知到底具体是哪里出了问题。你只能查看浏览器的控制台以得知具体是哪里出现了错误。

什么情况下需要 CORS

  • 由 XMLHttpRequest 或 Fetch 发起的跨域 HTTP 请求。
  • Web 字体 (CSS 中通过 @font-face 使用跨域字体资源)
  • WebGL 贴图
  • 使用 drawImage 将 Images/video 画面绘制到 canvas
  • 样式表(使用 CSSOM)(通过JS操作CSS树时使用到的资源)
    • CSS Object Model(CSSOM)是所有CSS选择器的映射,以及每个选择器的相关属性(以树的形式),具有根节点、兄弟、后代、子级和其他关系。(样式树)
    • CSS对象模型也是一组允许从JavaScript操作CSS的API。

若干访问控制场景(如何设置服务器响应头实现对CORS的支持)

简单请求

  • 某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”。若请求满足所有下述条件,则该请求可视为“简单请求”:(注意是所有)

    • 使用下列方法之一

      • GET
      • HEAD:请求资源的头部信息, 并且这些头部与 HTTP GET 方法请求时返回的一致.
      • POST:发送数据给服务器
    • Fetch 规范定义了对 CORS 安全的首部字段集合,以下是可以人为设定的首部字段:
      • Accept:用来告知服务器,客户端可以处理的内容类型,这种内容类型用MIME类型来表示。

      • Content-Type 仅限于下列三者之一 :Content-Type 实体头部用于指示资源的MIME类型 media type
        • text/plain 文本文件默认值。即使它意味着未知的文本文件,但浏览器认为是可以直接展示的。
        • multipart/form-data 用于HTML表单从浏览器发送信息给服务器。
        • application/x-www-form-urlencoded 数据被编码为名称/值对。标准的编码格式,在get中表现为(name1=value1&name2=value2…)
      • Accept-Language:允许客户端声明它可以理解的自然语言,以及优先选择的区域方言。
        • 借助内容协商机制,服务器可以从诸多备选项中选择一项进行应用, 并使用Content-Language 应答头通知客户端它的选择。
        • 浏览器会基于其用户界面语言来为这个请求头设置合适的值。注意:用户可能会想要浏览非本地用户界面语言的页面。
      • Content-Language:是一个 entity header (实体消息首部),用来说明访问者希望采用的语言或语言组合,这样的话用户就可以根据自己偏好的语言来定制不同的内容。(应该是用在响应中,告诉用户该实体适用于使用何种语言的人)
        • 假如设置了这样一条消息首部( "Content-Language: de-DE" ),那么说明这份文件是为说德语的人提供的(当然这并不意味着文件本身就是用德语写的)
        • 如果没有指明 Content-Language,那么默认地,文件内容是提供给所有语言的访问者使用的。
      • DPR(草案阶段的请求头)
      • Downlink(草案阶段的请求头)
      • Save-Data(草案阶段的请求头)
      • Viewport-Width(草案阶段的请求头)
      • Width(草案阶段的请求头)
    • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器(没有对XMLHttpRequestUpload 对象注册监听)
      • XMLHttpRequest.upload 属性返回一个 XMLHttpRequestUpload对象,用来表示上传的进度
    • 请求中没有使用 ReadableStream 对象。
      • 流操作API中的ReadableStream 接口呈现了一个可读取的二进制流操作。
      • Fetch API 通过Response的属性 body提供了一个具体的 ReadableStream 对象。https://www.cnblogs.com/qq3279338858/p/11057795.html
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml [XML Data]
  • Origin 表明该请求来源于。该首部用于 CORS 请求或者 POST 请求。除了不包含路径信息,该字段与 Referer 首部字段相似。

    • 有时候将该字段的值置空是有用的,例如,资源由一个 data URL 指定。
    • 不管是否为跨域请求,ORIGIN 字段总是被发送。
  • Referer 首部包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。
    • 服务端一般使用 Referer 首部识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。
    • 在以下两种情况下,Referer 不会被发送:
      • 来源页面采用的协议为表示本地文件的 "file" 或者 "data" URI;
      • 当前请求页面采用的是非安全协议,而来源页面采用的是安全协议(HTTPS)。
  • Vary 是一个HTTP响应头部信息,它决定了对于未来的一个请求头,应该用一个缓存的回复(response)还是向源服务器请求一个新的回复。
    • 它被服务器用来表明在 content negotiation algorithm(内容协商算法)中选择一个资源代表的时候应该使用哪些头部信息(headers).
    • 例如你提供给移动端的内容是不同的,可用防止你客户端误使用了用于桌面端的缓存。Vary: User-Agent
  • Access-Control-Allow-Origin 响应头指定了该响应的资源是否被允许与给定的origin共享。
    • 对于不需具备凭证(credentials)的请求,服务器会以“*”作为通配符,从而允许所有域都具有访问资源的权限。
    • 如需允许https://developer.mozilla.org访问您的资源,您可以设置:Access-Control-Allow-Origin: https://developer.mozilla.org
    • 如果服务器未使用“*”,而是指定了一个域,那么为了向客户端表明服务器的返回会根据Origin请求头而有所不同,必须在Vary响应头中包含Origin。(要使用该缓存,新请求的Origin必须和缓存请求的相同)

预检请求

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

    • 使用了下面任一 HTTP 方法:

      • PUT:使用请求中的负载创建或者替换目标资源
      • DELETE
      • CONNECT:开启一个客户端与所请求资源之间的双向沟通的通道。
      • OPTIONS:用于获取目的资源所支持的通信选项。
      • TRACE:实现沿通向目标资源的路径的消息环回(loop-back)测试 ,提供了一种实用的 debug 机制。(测试接口状态的方法?)
      • PATCH:用于对资源进行部分修改,不同于 PUT 方法,而与 POST 方法类似,PATCH 方法是非幂等的,这就意味着连续多个的相同请求会产生不同的效果。
    • 人为设置了 CORS 安全的首部字段集合之外的其他首部字段。(注意是之外,例如自定义头部)
    • Content-Type 的值不属于简单请求的那几类
    • 请求中的XMLHttpRequestUpload 对象注册了任意多个事件监听器。
    • 请求中使用了ReadableStream对象。
  • 大多数浏览器不支持针对于预检请求的重定向。如果一个预检请求发生了重定向,浏览器将报告错误(已被废弃,需要注意浏览器是否实现)
 1.OPTIONS /resources/post-here/ HTTP/1.1
2.Host: bar.other
3.User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
4.Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5.Accept-Language: en-us,en;q=0.5
6.Accept-Encoding: gzip,deflate
7.Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
8.Connection: keep-alive
9.Origin: http://foo.example
10.Access-Control-Request-Method: POST
11.Access-Control-Request-Headers: X-PINGOTHER, Content-Type
12.
13.
14.HTTP/1.1 200 OK
15.Date: Mon, 01 Dec 2008 01:15:39 GMT
16.Server: Apache/2.0.61 (Unix)
17.Access-Control-Allow-Origin: http://foo.example
18.Access-Control-Allow-Methods: POST, GET, OPTIONS
19.Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
20.Access-Control-Max-Age: 86400
21.Vary: Accept-Encoding, Origin
22.Content-Encoding: gzip
23.Content-Length: 0
24.Keep-Alive: timeout=2, max=100
25.Connection: Keep-Alive
26.Content-Type: text/plain
  • Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法。
  • Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求首部字段:X-PINGOTHER 与 Content-Type。
  • Access-Control-Allow-Methods 表明服务器允许客户端使用 POST, GET 和 OPTIONS 方法发起请求。
  • Access-Control-Allow-Headers 表明服务器允许请求中携带字段 X-PINGOTHER 与 Content-Type。
  • Access-Control-Max-Age 表明该响应的有效时间为 86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求。浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

附带身份凭证的请求

  • 一般而言,对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息(默认)
  • Fetch 与 CORS 的一个有趣的特性是,可以基于 HTTP cookies 和 HTTP 认证信息发送身份凭证?
    • Fetch API中的Request() 构造器中的credentials 选项https://www.cnblogs.com/qq3279338858/p/11057795.html
  • 将 XMLHttpRequest 的 withCredentials 标志设置为 true,从而向服务器发送 Cookieshttps://www.cnblogs.com/qq3279338858/p/10882479.html
  • 附带身份凭证的请求
    • 如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true ,浏览器将不会把响应内容返回给请求的发送者。
    • 请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。
    • 如果响应首部中携带了 Set-Cookie 字段,尝试对 Cookie 进行修改。如果操作失败,将会抛出异常。
  • Access-Control-Allow-Credentials:
    • Credentials(身份凭证)可以是 cookies, authorization headers 或 TLS client certificates。

      • authorization headers:Authorization 请求消息头含有服务器用于验证用户代理身份的凭证,通常会在服务器返回401 Unauthorized 状态码以及WWW-Authenticate 消息头之后在后续请求中发送此消息头。
      • TLS client certificates TLS客户端证书,TLS是传输层安全协议,HTTPS基于它实现
    • 当作为对预检请求的响应的一部分时,这能表示是否真正的请求可以使用credentials(身份凭证)。
    • 简单 GET 请求不会被预检;如果对此类请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页。

HTTP 响应首部字段

Access-Control-Expose-Headers

  • 在跨域访问时,XMLHttpRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头。

    • Cache-Control、Expires、Last-Modified、Pragma 浏览器缓存相关头部,见https://www.cnblogs.com/qq3279338858/p/10393881.html
    • Content-Type、Content-Language 见当前文章
  • Access-Control-Expose-Headers 头让服务器把允许浏览器访问的头放入白名单Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

Access-Control-Allow-Origin

  • 前文已有

Access-Control-Max-Age

  • 前文已有

Access-Control-Allow-Credentials

  • 前文已有

Access-Control-Allow-Methods

  • 前文已有

Access-Control-Allow-Headers

  • 前文已有

HTTP 请求首部字段

  • 这些首部字段无须手动设置。 当开发者使用 XMLHttpRequest 对象发起跨域请求时,它们已经被设置就绪。

Origin

  • 前文已有

Access-Control-Request-Method

  • 前文已有

Access-Control-Request-Headers

  • 前文已有

安全 - CORS(脚本请求等)的更多相关文章

  1. ajax请求头加Token时发生的跨域(CORS)请求问题

    首先描述下问题:需求是在请求头中加入token,我在ajax请求数据时添加了请求头‘Authorization’字段,并添加了响应的token值,在请求数据的时候浏览器报错如下: Request he ...

  2. JMeter 脚本请求错误 HTTP Status 415 的解决

    然后在http请求上点击右键,添加配置元件-http信息头管理器,在信息头管理器上,添加一个参数,名称:Content-Type,值:application/json.然后在http请求上,conte ...

  3. cors 预请求

    1.CORS的其他限制 默认允许的方法只有:GET.HEAD.POST默认允许的Content-Type:text/plain.multipart/form-data.applicaton/x-www ...

  4. Pycharm----设置默认脚本请求头

    每次新建py文件,均需要在文件头部加上编码声明,每次的手动添加比较麻烦,因此设置自动生成,也可添加作者.时间等等,详见如下: 设置后的样例显示: 操作方式: 操作完如上的截图步骤,再次新建一个py文件 ...

  5. 配置CORS代理请求

    参考资料: Vue-CLI 3.x 跨域问题处理 使用代理设置:见官方文档 配置代理 新建配置文件 在 package.json 文件的同级目录下创建 vue.config.js 文件,文件的格式应该 ...

  6. SpringBoot配置Cors解决跨域请求问题

    一.同源策略简介 同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源. 同源策略是浏览器安全的基石. 什么是源 源[or ...

  7. SpringBoot使用CORS解决跨域请求问题

    什么是跨域? 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源. 同源策略是浏览器安全的基石. 如果一个请求地址里面的协议.域名和端口号都相同,就属于同源. ...

  8. 4 伪ajax:jsonp、cors 跨域请求

    一.同源策略 https://www.cnblogs.com/yuanchenqi/articles/7638956.html 同源策略(Same origin policy)是一种约定,它是浏览器最 ...

  9. 同源策略与CORS跨域请求

    一.同源策略 1.简介 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源 ...

随机推荐

  1. 从linux命令行分享文件:bashupload.com和transfer.sh

    背景 传输文件是一个常见的需求,简单的做法是通过即时通讯工具,邮件,网盘完成. 但当分享或接收的一端为远程服务器,只有命令行可以操作时,一个能支持在命令行完成分享和下载的工具,就会省下不少麻烦. 下面 ...

  2. pt-query-digest 慢日志监控

    一.安装percona-toolkit,以centos为例 yum -y install https://repo.percona.com/yum/percona-release-latest.noa ...

  3. Head First设计模式——代理模式

    在HeadFirst设计模式中代理模式用了比较多的篇幅来讲解,其中的例子我感觉有些繁琐,所以我们这篇就不按照惯例用例子来阐述代理模式了.我们直接进入正题,分析模式本身的设计和解决的问题. 远程代理模式 ...

  4. Java @Deprecated Annotation(注解)

    在本部分的快速指南中,我们将会查看 Java 的 deprecated API 和如何在程序中使用 @Deprecated 注解. @Deprecated Annotation(注解) 作为程序的进化 ...

  5. Apache Log4j 反序列化代码执行(CVE-2019-17571) 漏洞分析

    Apache Log4j 漏洞分析 仅用于研究漏洞原理,禁止用于非法用途,后果自负!!! CVE-2019-17571 漏洞描述 Log4j是美国阿帕奇(Apache)软件基金会的一款基于Java的开 ...

  6. 10.Android-SharedPreferences使用

    1.SharedPreferences介绍 SharedPreferences,它是一个轻量级的配置文件类,用于保存软件配置参数. 采用xml文件形式存储在/data/data/包名/shared_p ...

  7. warning Unexpected use of undefined no-undefined

    报错翻译:警告意外使用未定义的no-undefined(谷歌这次翻译的不行) 报错原因undefined直接使用了,如下↓ 其实报错的意思就是这样不安全,看下面一个例子 var foo = undef ...

  8. springboot + mybatis 支持oracle和mysql切换含源码

    1.springboot 启动类加入bean 如下 // DatabaseIdProvider元素主要是为了支持不同的数据库@Beanpublic DatabaseIdProvider getData ...

  9. 到2029年MRAM收入将增长170倍

    一份新市场报告预计,从2018年到2029年,独立MRAM和STT-MRAM的收入将增长170倍,达到近40亿美元的收入.下一代内存技术的增长将主要由取代效率较低的内存技术(例如NOR闪存和SRAM) ...

  10. Sercet sharing

    Secret Sharing Shamir门限 条件: \(0<k\leq n<p\) \(S<p,p\)是素数 Lagrange插值公式 \[ f(x)=\sum^{k}_{j=1 ...