艾瑞可erik

W3C

跨源资源共享

W3C建议2014年1月16日

这个版本:
http://www.w3.org/TR/2014/REC-cors-20140116/
最新版本:
http://www.w3.org/TR/cors/
之前的版本:
http://www.w3.org/TR/2013/PR-cors-20131205/
http://www.w3.org/TR/2013/CR-cors-20130129/
http://www.w3.org/TR/2012/WD-cors-20120403/
http://www.w3.org/TR/2010/WD-cors-20100727/
http://www.w3.org/TR/2009/WD-cors-20090317/
http://www.w3.org/TR/2008/WD-access-control-20080912/
http://www.w3.org/TR/2008/WD-access-control-20080214/
http://www.w3.org/TR/2007/WD-access-control-20071126/
http://www.w3.org/TR/2007/WD-access-control-20071001/
http://www.w3.org/TR/2007/WD-access-control-20070618/
http://www.w3.org/TR/2007/WD-access-control-20070215/
http://www.w3.org/TR/2006/WD-access-control-20060517/
http://www.w3.org/TR/2005/NOTE-access-control-20050613/
编辑:
Anne van Kesteren (前身为Opera Software ASA)< annevk@annevk.nl >

请注意,本文档可能有勘误表

该规范的英文版是唯一的规范版本。也可以提供非规范性 翻译


抽象

本文档定义了一种启用客户端跨源请求的机制。使API能够对资源进行跨源请求的规范可以使用本规范定义的算法。如果在http://example.org资源上使用这样的API,则资源http://hello-world.example可以使用本规范描述的机制(例如,指定Access-Control-Allow-Origin: http://example.org为响应头)来选择加入 ,这将允许从该源获取该资源 http://example.org

本文件的状态

本节介绍本文档发布时的状态。其他文件可能会取代本文件。有关当前W3C出版物的列表以及该技术报告的最新修订版,请参见 W3C技术报告索引,网址为http://www.w3.org/TR/。

本文档已由W3C成员,软件开发人员以及其他W3C小组和相关​​方进行审核,并由主管认可为W3C建议书。它是一份稳定的文件,可用作参考资料或从其他文件中引用。W3C在制定建议书方面的作用是提请注意规范并促进其广泛部署。这增强了Web的功能和互操作性。

此COR3的W3C建议书由 Web应用程序(WebApps)和 Web应用程序安全性(WebAppSec)工作组联合制作,并由WebAppSec工作组发布。自上次出版物作为拟议建议书以来未做任何更改。

如果您想对本文档发表评论,请发送至 public-webappsec@w3.org订阅存档)。

本文件由根据2004年2月5日W3C专利政策运营的团体制作W3C维护了WebAppSec WGWebApps WG 与该组可交付成果相关的任何专利公开的公开列表; 该页面还包括披露专利的说明。具有个人认为包含基本要求的专利的实际知识的个人必须根据W3C专利政策的第6节披露该信息

通过发布本建议书,W3C希望此跨域资源共享建议书中指定的功能不会受到HTML5或HTTP状态码308的更改的影响,因为这些规范分别进入建议书和RFC状态。

提供了初步实施报告补充了自候选建议书以来的变化

目录

  1. 1简介
  2. 2一致性
  3. 3术语
  4. 4安全考虑因素
  5. 5语法
    1. 5.1Access-Control-Allow-Origin响应标题
    2. 5.2Access-Control-Allow-Credentials响应标头
    3. 5.3Access-Control-Expose-Headers响应标头
    4. 5.4Access-Control-Max-Age响应标题
    5. 5.5Access-Control-Allow-Methods响应标头
    6. 5.6Access-Control-Allow-Headers响应标头
    7. 5.7Origin请求标头
    8. 5.8Access-Control-Request-Method请求标头
    9. 5.9Access-Control-Request-Headers请求标题
  6. 6资源处理模型
    1. 6.1简单的跨源请求,实际请求和重定向
    2. 6.2预检请求
    3. 6.3安全
    4. 6.4实施注意事项
  7. 7用户代理处理模型
    1. 7.1跨源请求
      1. 7.1.1处理对跨源请求的响应
      2. 7.1.2跨源请求状态
      3. 7.1.3来源
      4. 7.1.4简单的跨源请求
      5. 7.1.5带预检的跨源请求
      6. 7.1.6预检结果缓存
      7. 7.1.7通用跨源请求算法
    2. 7.2资源共享检查
    3. 7.3安全
  8. 8 CORS API规范建议
    1. 8.1构建跨源请求
    2. 8.2处理跨源重定向的同源
    3. 8.3处理跨源请求状态
    4. 8.4安全
  9. 参考
  10. 致谢

1简介

本节不具有规范性。

用户代理通常将同源限制应用于网络请求。这些限制阻止从一个源运行的客户端Web应用程序获取从另一个源检索的数据,并且还限制可以自动启动到不同于正在运行的应用程序源的目标的不安全HTTP请求。

在遵循此模式的用户代理中,网络请求通常包括具有跨源请求的用户凭证,包括HTTP身份验证和cookie信息。

该规范以多种方式扩展了该模型:

此规范是其他规范的构建块,即所谓的CORS API规范,它定义了如何使用此规范。示例是Server-Sent Events和XMLHttpRequest。 [EVENTSOURCE] [XHR]

CORS wiki页面提供了有关此文件的更多背景信息。

如果资源作者有一个简单的文本资源, http://example.com/hello其中包含字符串“Hello World!” 并且希望http://hello-world.example能够访问它,响应与本规范引入的标头相结合可能如下所示:

Access-Control-Allow-Origin: http://hello-world.example

Hello World!

使用XMLHttpRequest客户端Web应用程序http://hello-world.example可以访问此资源,如下所示:

var client = new XMLHttpRequest()
client.open("GET", "http://example.com/hello")
client.onreadystatechange = function() { /* do something */ }
client.send()

如果资源作者希望能够使用除简单方法之外的方法处理跨源请求,则会稍微复杂一些 在这种情况下,作者需要回复使用该OPTIONS方法的预检请求, 然后需要处理使用所需方法的实际请求(DELETE在此示例中)并给出适当的响应。对预检请求的响应可以指定以下标头:

Access-Control-Allow-Origin: http://hello-world.example
Access-Control-Max-Age: 3628800
Access-Control-Allow-Methods: PUT, DELETE

Access-Control-Max-Age 报头指示的响应多久可以被缓存,以使得后续请求,在规定时间内,没有预检请求必须制成。Access-Control-Allow-Methods 报头指示了可以在实际请求中使用的方法。对实际请求的响应可以只包含此标头:

Access-Control-Allow-Origin: http://hello-world.example

调用附加预检请求的复杂性是用户代理的任务。XMLHttpRequest再次使用 并假设应用程序托管在http://calendar.example/app作者可以使用以下ECMAScript片段:

function deleteItem(itemId, updateUI) {
  var client = new XMLHttpRequest()
  client.open("DELETE", "http://calendar.example/app")
  client.onload = updateUI
  client.onerror = updateUI
  client.onabort = updateUI
  client.send("id=" + itemId)
}

2一致性

此规范是为资源作者和用户代理编写的。它包含定义API的规范建议,这些规范使用本规范中定义的 跨源请求算法 - CORS API规范 - 以及一般 安全注意事项部分包括对客户端Web应用程序作者的一些建议。

除了标记为非规范性的章节和附录外,本说明书中的所有图表,示例和注释都是非规范性的。本规范中的其他所有内容都是规范性的。

在本规范中,必须和可能的解释如RFC 2119中所述。 [RFC2119]

作为算法的一部分在命令中表达的要求(例如,“终止算法”)将被解释为引入算法时使用的关键词(例如必须)的含义。

符合资源的是实现本规范中列出的适用于资源的所有要求的资源。

符合用户代理是实现本规范中列出的适用于用户代理的所有要求的用户代理。

用户代理和资源作者可以使用任何算法来实现该规范,只要最终结果与规范的算法将获得的结果无法区分即可。

3术语

本规范中的一些术语来自 Web Origin ConceptHTMLHTTPURI[原创] [HTML] [HTTP] [URI]

术语通常在整个说明书中定义。但是,这里定义了几个不适合其他地方的定义。

区分大小写的方式比较两个字符串 意味着准确地比较它们,代码点的代码点。

ASCII不区分大小写的方式比较两个字符串 意味着准确地比较它们,代码点的代码点,除了U + 0041 LATIN CAPITAL LETTER A到U + 005A LATIN CAPITAL LETTER Z范围内的字符和U +范围内的相应字符0061拉丁文小写字母A至U + 007A拉丁文小写字母Z也被认为是匹配的。

将字符串转换为ASCII小写 意味着将U + 0041 LATIN CAPITAL LETTER A中的所有字符替换为U + 005A LATIN CAPITAL LETTER Z,其中包含U + 0061范围内的相应字符LATIN SMALL LETTER A至U + 007A LATIN SMALL LETTER Z )。

出于本规范的目的,术语用户凭证意味着将根据用户代理之前与源的交互发送的cookie,HTTP身份验证和客户端SSL证书。具体而言,它不涉及代理身份验证或Origin标头。 [饼干]

术语“ 交叉起源”用于表示 不同的起源

方法被说成是一个 简单的方法,如果是 大小写敏感的用于执行下列操作之一匹配:

被说成是一个 简单包头如果报头字段名称是一个 ASCII不区分大小写为匹配AcceptAccept-Language或者Content-Language,或者如果它是一个ASCII不区分大小写的用于匹配 Content-Type和报头字段值的媒体类型(不包括参数)是一个ASCII不区分大小写匹配 application/x-www-form-urlencodedmultipart/form-datatext/plain

被说成是一个 简单的响应报头,如果首部字段名称是一个ASCII不区分大小写的以下中的一个匹配:

解析的报头的报头必须按照相应的生产ABNF在解析语法部分。如果标题与生产不匹配,则表示 标题解析失败

4安全考虑因素

本节不具有规范性。

本说明书中列出了安全要求和注意事项。本节列出了不适合其他任何地方的建议。


已经将简单的跨源请求定义为与可能由当前部署的不符合该规范的用户代理生成的请求一致。在此规范之外生成的简单跨源请求(例如使用 GET 来自元素的POST交叉源GET请求的交叉源请求script)通常包括 用户凭证,因此必须始终准备符合此规范的资源以期望简单的跨源请求凭证。

因此,简单请求具有除检索之外的重要性的资源必须通过要求在明确提供的请求内容中包含不可读的令牌来保护自己免受跨站请求伪造(CSRF)。 [CSRF]

该规范定义了如何在外部源中授权应用程序的实例,在用户代理中执行,以访问HTTP响应中的资源表示。某些类型的资源不应试图指定特定的授权来源,而应拒绝或允许所有来源。

  1. 对来自其他来源的应用程序(例如登录页面)无用的资源不应返回 Access-Control-Allow-Origin 标头。资源仍然必须保护自己免受CSRF攻击,例如要求在明确提供的请求内容中包含不可语量的令牌。此类资源的安全属性不受符合此规范的用户代理的影响。

  2. 可公开访问且没有访问控制检查的资源始终可以安全地返回Access-Control-Allow-Origin 值为“ *标头

  3. GET其实体主体恰好解析为的ECMAScript可以返回响应 Access-Control-Allow-Origin 报头的值是“ *”的有,因为它可以使用HTML来访问跨来源没有敏感评论 script元件。如果需要,这些资源可以实现如上所述的访问控制和CSRF保护。

使用用户凭据Origin标头进行的请求需要特殊考虑。

  1. 当请求具有检索以外的重要性,并且当依赖于Origin头部时,资源必须小心区分授权请求(包括其副作用)和授权访问响应中该资源的表示。

    1. 应仅使用用户权限和请求源的交集来执行请求的授权。

    2. 资源通常适用于要求授权仪式,该授权仪式明确要求用户同意具有凭证的跨源请求来自给定来源。在这种情况下,明确地将安全性令牌作为跨源请求的一部分传递可以消除关于授权范围的任何歧义。OAuth就是这种模式的一个例子。 [OAUTH]

  2. 在以下情况下,在跨源请求中使用用户凭据是合适的:

    1. 使用本规范中定义的凭证的跨源请求来替代经过身份验证的资源共享的替代方法,例如服务器到服务器反向通道,JSONP或跨文档消息传递。 [JSONP] [HTML]

      在某些情况下,此替换可能会暴露额外的攻击面,因为与服务器到服务器反向通道相比,请求源中的跨站点脚本漏洞可允许针对所请求资源提升特权。

      作为JSONP样式的跨源凭证请求的替代,使用此规范显着改善了请求应用程序的安全状态,因为它提供跨源数据访问,而JSONP通过跨源代码注入进行操作。

      作为依赖于将资源,凭证加载到HTML iframe元素中,并随后采用跨文档消息传递或其他跨源侧信道的跨源通信技术的替代,该规范提供了大致相等的安全状态。同样,必须验证从不完全信任的起源接收的数据以符合预期格式和授权值。

    2. 对于除检索之外没有任何意义的资源的请求,以及仅使用凭据来为其他可公开访问的信息提供用户特定的自定义的请求。在这种情况下,限制对某些来源的访问可以通过防止用于识别用户的定制来保护用户隐私,除非在授权的来源。

  3. 当此规范用于具有除检索之外的重要性且涉及来自两个以上来源的协调或来自两个以上来源的数据的请求时(例如,在允许编辑,打印和存储的资源之间,每个来自不同的来源)请求应该设置省略凭证标志和资源应该使用在请求内容中明确提供的安全令牌来执行授权,特别是如果起源并非全部相互完全信任。

    在这种多源方案中,其中一个来源的恶意资源可能能够将用户代理作为混淆的代理人登记,并通过滥用与跨源请求一起发送的用户凭证来提升其特权。避免此类攻击需要协调应用程序明确了解每个来源的权限范围,并且在协调的每个步骤中仔细验证收到的所有参数和指令,以确保隐含的影响不超过原始主体的权限。 [困惑]

    考虑到在多源交互中避免此类漏洞的困难,建议不要使用由用户代理自动附加到请求的用户凭证,而是指定授权的特定功能和资源的安全令牌作为显式内容的一部分传递请求。OAuth再次提供了这种模式的示例。


强烈建议客户端Web应用程序的作者验证从跨源资源检索的内容,因为它可能有害。

未由特定主机名唯一标识和/或映射到特定端口的Web应用程序不一定具有唯一的来源,因此将无法安全地利用本规范中定义的机制。这是因为原点仅由方案,主机名和端口组成。

例如,其URL类型 和应用程序名称部分的Web应用程序是区分Web应用程序与也在example.org上运行的其他Web应用程序所必需的,将无法安全地使用本规范中定义的机制。example.org/app-name/

将Web应用程序映射到不同的 来源 对于安全Web应用程序至关重要。

5语法

本节定义了本规范引入的新标头的语法。它还提供了每个标头功能的简短描述。

资源处理模型 部分详细说明资源如何在响应中使用这些头。同样, 用户代理处理模型 部分详细说明了用户代理如何使用这些标头。

本节中使用的ABNF语法来自HTTP / 1.1。 [HTTP]

HTTP / 1.1用作ABNF基础,以确保新标头具有与该规范中引入的标头相同的解析规则。

HTTP / 1.1当前不会使标题值定义中隐含的主要OWS,但此处假设该形式。

5.1Access-Control-Allow-Origin响应标题

Access-Control-Allow-Origin 报头指示是否一个资源可以被共享的基于通过返回的值Origin请求头,“*”,或在响应“空”。ABNF:

Access-Control-Allow-Origin =“Access-Control-Allow-Origin”“:” origin-list-or-null | “*”

在实践中, origin-list-or-null生产受到更多限制。它不是允许以空格分隔的原点列表 ,而是单个原点或字符串“ null”。

5.2Access-Control-Allow-Credentials响应标头

Access-Control-Allow-Credentials 报头指示是否请求的响应可以在被暴露省略凭证标志未设置。当对预检请求的响应的一部分时,它指示 实际请求可以包括用户凭证ABNF:

Access-Control-Allow-Credentials:“Access-Control-Allow-Credentials”:“”true
                            true:%x74.72.75.65; “真实”,区分大小写

5.3Access-Control-Expose-Headers响应标头

Access-Control-Expose-Headers 报头指示该标头是安全,以暴露到CORS API规范的API。ABNF:

Access-Control-Expose-Headers =“Access-Control-Expose-Headers”“:”#field-name

5.4Access-Control-Max-Age响应标题

Access-Control-Max-Age 报头指示多长时间的结果预检请求 可以在被缓存预检结果缓存ABNF:

Access-Control-Max-Age =“Access-Control-Max-Age”“:” delta-seconds

5.5Access-Control-Allow-Methods响应标头

Access-Control-Allow-Methods 报头指示,作为响应于一部分 预检要求,可在过程中使用的方法 的实际请求

` Allow`标题与CORS协议的目的无关。ABNF:

Access-Control-Allow-Methods:“Access-Control-Allow-Methods”“:”#Method

5.6Access-Control-Allow-Headers响应标头

Access-Control-Allow-Headers 报头指示,作为响应于一部分 预检请求,其中报头字段名称可以在过程中使用实际的请求ABNF:

Access-Control-Allow-Headers:“Access-Control-Allow-Headers”“:”#field-name

5.7Origin请求标头

Origin 报头指示了跨来源请求预检请求从发起。 [起源]

5.8Access-Control-Request-Method请求标头

Access-Control-Request-Method 报头指示该方法将在使用 实际的请求作为一部分 预检请求ABNF:

访问控制请求方法:“访问控制 - 请求 - 方法”:“ 方法

5.9Access-Control-Request-Headers请求标题

Access-Control-Request-Headers 报头指示哪些报头将在使用 实际的请求作为一部分 预检请求ABNF:

Access-Control-Request-Headers:“Access-Control-Request-Headers”“:”#field-name

6资源处理模型

本节介绍资源必须实现的处理模型。资源可能必须处理的每种类型的请求都在其自己的小节中描述。

本规范描述的资源共享策略绑定到特定资源。出于本节的目的,每个资源都绑定到以下内容:

6.1简单的跨源请求,实际请求和重定向

响应于简单的跨源请求实际请求,资源指示是否共享响应。

如果资源已重新定位,则表示是否共享其新URL

资源必须使用以下一组步骤来确定在响应中使用哪些其他标头:

  1. 如果Origin标头不存在则终止这组步骤。该请求超出了本规范的范围。

  2. 如果Origin 标头的值不是原始列表中任何值区分大小写的匹配项,请不要设置任何其他标头并终止这组步骤。

    始终匹配是可以接受的,因为 原始列表可以是无界的。

  3. 如果资源支持凭据,请添加单个Access-Control-Allow-Origin 标头,并将 标头的值Origin 作为值,并添加单个 Access-Control-Allow-Credentials 标头,并将区分大小写的字符串“ true”作为值。

    否则,添加一个 Access-Control-Allow-Origin 标头,标头值 Origin或字符串“ *”作为值。

    字符串“ *”不能用于支持凭据的资源

  4. 如果公开的标头列表不为空,则添加一个或多个 Access-Control-Expose-Headers 标头,并将公开标头列表中给出的标头字段名称作为值

如果不添加适当的标题资源也可以清除预检结果缓存,所有条目的 起源区分大小写 的价值匹配的Origin 标题和URL区分大小写的匹配 URL的资源。

6.2预检请求

响应预检请求,资源指示它愿意处理哪些方法和标题(除 简单方法简单标题之外)以及它是否支持凭证

资源必须使用以下一组步骤来确定在响应中使用哪些其他标头:

  1. 如果Origin标头不存在则终止这组步骤。该请求超出了本规范的范围。

  2. 如果Origin 标头的值不是原始列表中任何值区分大小写匹配,则不设置任何其他标头并终止此组步骤。

    始终匹配是可以接受的,因为 原始列表可以是无界的。

    Origin报头只能包含单个原点作为用户代理将不跟随重定向。

  3. 方法是值作为结果 进行解析Access-Control-Request-Method 报头。

    如果没有 Access-Control-Request-Method 标头或解析失败,请不要设置任何其他标头并终止这组步骤。该请求超出了本规范的范围。

  4. 头字段的名称是值的结果, 分析Access-Control-Request-Headers 头。

    如果没有 Access-Control-Request-Headers 标题,则header header-name为空列表。

    如果解析失败,请不要设置任何其他标头并终止这组步骤。该请求超出了本规范的范围。

  5. 如果method不是方法列表中 任何值区分大小写匹配,则不设置任何其他标头并终止此组步骤。

    始终匹配是可以接受的,因为 方法列表可以是无界的。

  6. 如果任何标头字段名称不是对标题列表中的任何值ASCII不区分大小写匹配, 则不设置任何其他标头并终止此组步骤。

    始终匹配是可以接受的,因为 标题列表可以是无界的。

  7. 如果资源支持凭据,请添加单个Access-Control-Allow-Origin 标头,并将 标头的值Origin 作为值,并添加单个 Access-Control-Allow-Credentials 标头,并将区分大小写的字符串“ true”作为值。

    否则,添加一个 Access-Control-Allow-Origin 标头,标头值 Origin或字符串“ *”作为值。

    字符串“ *”不能用于支持凭据的资源

  8. (可选)添加单个 Access-Control-Max-Age 标头,其值为允许用户代理缓存请求结果的秒数。

  9. 如果method是一种简单方法, 则可以跳过此步骤。

    添加一个或多个 Access-Control-Allow-Methods方法列表(的一部分)组成的标头

    如果方法是一种简单的方法,则不需要列出,但这不是禁止的。

    由于方法列表可以是无界的,因此只需返回由Access-Control-Request-Method(如果支持)指示 的方法就足够了。

  10. 如果每个标题字段名称都是 简单标题而没有标题字段名称Content-Type,则可以跳过此步骤。

    添加一个或多个 Access-Control-Allow-Headers标题列表(的一部分)组成 的标题

    如果标题字段名称是简单标题而不是Content-Type,则不需要列出它。 Content-Type将被列为其值的一个子集使其符合简单标题

    由于标头列表可以无限制,因此只需从Access-Control-Allow-Headers返回支持的标即可。

6.3安全

本节不具有规范性。

强烈建议资源作者确保使用安全方法的请求,例如GETOPTIONS没有副作用,以便潜在的攻击者无法轻易修改用户的数据。如果像这样建立资源,攻击者实际上必须在起源列表上做出伤害。

除了检查Origin 标题之外,强烈建议资源作者也检查 Host标题。也就是说,确保该标头提供的主机名与资源所在的服务器的主机名匹配。这将提供针对DNS重新绑定攻击的保护。

为了提供资源共享策略的完整性保护,鼓励使用SSL / TLS。

6.4实施注意事项

本节不具有规范性。

希望使自己能够与多个共享 Origins但不能均匀响应的资源"*" 必须在实践中Access-Control-Allow-Origin 动态地生成头部以响应他们希望允许的每个请求。因此,此类资源的作者应发送 Vary: OriginHTTP标头或提供其他适当的控制指令以防止缓存此类响应,如果跨源重用,则可能不准确。

7用户代理处理模型

本节介绍用户代理必须实现的处理模型。

本节中的处理模型需要由CORS API规范引用,该规范定义何时调用算法以及如何处理返回值。处理模型不适合独立使用。

7.1跨源请求

所述跨来源请求 算法采用以下参数:

请求网址

获取URL

请求URL被重定向的面改性。

请求方法

请求的方法。GET,除非明确设定。

作者请求标题

作者为请求设置的标头列表。空,除非明确设置。

请求实体主体

请求的实体主体。丢失,除非明确设置。

来源

请求来源

由于某些API的细节,这不能以通用方式定义,因此必须作为参数提供。

推荐人来源

一个DocumentURL用于确定 Referer标头。

手动重定向标志

自动遵循重定向时设置

省略凭证标志

设置何时在请求中排除用户凭据以及何时在响应中忽略cookie。

强制预检旗帜

在需要预检请求时设置

跨域请求算法可以通过谁希望允许它们定义了网络API的跨域请求CORS API规范使用。

CORS API规范可以自由地限制跨源请求的能力例如, 可以始终设置省略凭证标志

跨来源请求被调用算法,这些步骤必须遵循:

  1. 如果由于某种原因,用户代理不希望使请求终止此算法并将 跨源请求状态设置网络错误

    请求的URL可能已通过某种方式的用户列入黑名单。

  2. 如果满足以下条件,请遵循 简单的跨源请求算法:

  3. 否则,请使用预检算法遵循 跨源请求

使用一种方法跨域请求 简单笔者请求头那不是 简单的将有一个 预检要求,以确保资源能够处理这些头。(与使用不是简单方法的方法的请求类似 。)

7.1.1处理对跨源请求的响应

用户代理必须过滤掉除了那些简单响应标头之外的所有响应标头,或者 在将响应标头暴露给定义的API之前,字段名称是对标头的其中一个值(如果有)ASCII不区分大小写的匹配 Access-Control-Expose-Headers在CORS API规范中。

因此,getResponseHeader() 方法XMLHttpRequest不会暴露任何未在上面指出的标题。

7.1.2跨源请求状态

每个跨源请求都具有关联的 跨源请求状态 ,CORS API规范允许API进行 跨源请求可以挂钩。跨源请求的过程中最多可能需要两个不同的值 价值观是:

预检完成
用户代理即将发出实际请求
成功
资源可以共享。
中止错误
用户中止了请求。
网络错误
资源无法共享。当DNS错误,TLS协商失败或其他类型的网络错误发生时也使用。 这不包括指示某种类型错误的HTTP响应,例如HTTP状态代码410。

7.1.3来源

源原点是初始 原点该用户代理必须使用的Origin报头。它可以在重定向步骤中修改

7.1.4简单的跨源请求

以下步骤描述了用户代理必须为 简单的跨源请求执行的操作

  1. 发出请求时,应用make a request步骤并遵守下面请求规则

    如果未设置手动重定向标志且响应的HTTP状态代码为301,302,303,307或308

    应用重定向步骤

    如果最终用户取消请求

    应用中止步骤

    如果出现网络错误

    如果出现DNS错误,TLS协商失败或其他类型的网络错误,请应用网络错误步骤不要求任何类型的最终用户交互。

    这不包括指示某种类型错误的HTTP响应,例如HTTP状态代码410。

    除此以外

    执行资源共享检查如果它返回失败,请应用网络错误步骤否则,如果它返回pass,则终止此算法并将 跨源请求状态设置success实际上不要终止请求。

7.1.5带预检的跨源请求

为了保护资源免受在此规范存在之前不能源自某些用户代理的跨源请求,进行 预检请求以确保资源知道此规范。此请求的结果存储在 预检结果缓存中

以下步骤描述了用户代理必须对具有预检跨源请求执行的操作这是对非同源URL的请求,首先需要使用预检结果缓存条目或 预检请求进行授权

  1. 如果满足以下条件,请转到下一步:

    否则,请进行 预检请求请求URL原点 源来源使用 引荐源作为覆盖引荐源手动重定向标志块饼干标志组,使用该方法 OPTIONS,并具有以下附加约束:

    在进行预检请求时,应遵守以下请求规则

    如果最终用户取消请求

    应用中止步骤

    如果响应的HTTP状态代码不在2xx范围内

    应用网络错误步骤

    缓存和网络错误步骤,在这里不使用,因为这是关于一个实际的网络错误。

    如果出现网络错误

    如果出现DNS错误,TLS协商失败或其他类型的网络错误,请应用网络错误步骤不要求任何类型的最终用户交互。

    这不包括指示某种类型错误的HTTP响应,例如HTTP状态代码410。

    缓存和网络错误步骤,在这里不使用,因为这是关于一个实际的网络错误。

    否则(HTTP状态代码在2xx范围内)
    1. 如果资源共享检查返回失败,请应用缓存和网络错误步骤

    2. 方法成为空列表。

    3. 如果有一个或多 Access-Control-Allow-Methods 个头,则let 方法解析头的结果

      如果解析失败,则 应用缓存和网络错误步骤

    4. 如果方法仍然是空列表并且设置了 强制预检标志,则将请求方法附加 方法

      这确保 了仅因强制预检标志发生的预检请求被缓存。

    5. 标题为空列表。

    6. 如果有一个或多个 Access-Control-Allow-Headers则将标头作为解析标头的结果的值

      如果解析失败,则 应用缓存和网络错误步骤

    7. 如果请求方法不是 区分大小写在任何方法的比赛 方法,并且不是简单的方法,应用该缓存和网络错误的步骤

    8. 如果每个头的字段名 作者请求头是不是一个 ASCII不区分大小写在报头字段名称之一匹配标题和标题是不是一个简单的报头,应用 缓存和网络错误的步骤

    9. 如果由于某种原因用户代理无法提供 预检结果缓存(例如,由于磁盘空间有限),请转到整个步骤集(即实际请求)中的下一步

    10. 如果有一个 Access-Control-Max-Age 标题,请解析它并让 max-age为结果值。

      如果没有这样的头,则有多个这样的头,或者解析失败,让 max-age成为用户代理自行决定的值(允许为零)。

      如果用户代理对max-age字段值施加限制 并且 max-age大于该限制,则 max-age为限制。

    11. 对于每个方法的方法对其中有一个方法缓存比赛设置的 最大年龄的匹配项的字段值最大年龄

      对于每个方法的方法对其中有 没有 方法缓存匹配创建的新条目预检结果缓存设置如下各个领域:

      起源
      源产地
      网址
      请求的URL
      最大年龄
      最大年龄
      证书
      如果设置了省略凭证标志,则返回false,否则返回true。
      方法
      给定的方法。
      空。
    12. 对于存在标头高速缓存匹配头中的每个标,将匹配条目max-age字段值设置 max-age

      对于没有标头高速缓存匹配的标头中的每个标预检结果高速缓存中创建一个新条目,其中各种字段设置如下:

      起源
      源产地
      网址
      请求的URL
      最大年龄
      最大年龄
      证书
      如果设置了省略凭证标志,则返回false,否则返回true。
      方法
      空。
      给定的标题。
  2. 跨源请求状态设置预检完成

  3. 这是实际的要求发出请求时,应用 make a request步骤并遵守 下面请求规则

    如果响应的HTTP状态代码为301,302,303,307或308

    应用缓存和网络错误步骤

    如果最终用户取消请求

    应用中止步骤

    如果出现网络错误

    如果出现DNS错误,TLS协商失败或其他类型的网络错误,请应用网络错误步骤不要求任何类型的最终用户交互。

    这不包括指示某种类型错误的HTTP响应,例如HTTP状态代码410。

    除此以外

    执行资源共享检查如果它返回失败,请应用缓存和网络错误步骤否则,如果它返回pass,则终止此算法并将 跨源请求状态设置success实际上不要终止请求。

请考虑以下情形:

  1. 所述用户代理从API获取请求,例如 XMLHttpRequest,以执行使用自定义的横原点请求XMODIFY从方法 源原点 http://example.orghttp://blog.example/entries/hello-world

  2. 用户代理使用该方法 执行预检请求 使用适当的值包含 标头。OPTIONShttp://blog.example/entries/hello-worldOriginAccess-Control-Request-Method

  3. 对该请求的响应包括以下标头:

    Access-Control-Allow-Origin:http://example.org
    Access-Control-Max-Age:2520
    Access-Control-Allow-Methods:PUT,DELETE,XMODIFY
  4. 然后,用户代理使用该XMODIFY方法执行所需的请求 http://blog.example/entries/hello-world因为资源允许这样做。此外,在未来的四十二分钟内,不需要 预检请求

7.1.6预检结果缓存

如上所述,使用预检跨源请求 使用预检结果缓存此缓存由一组条目组成。每个条目包含以下字段:

起源
保留源来源
网址
保留请求URL
最大年龄
保留 Access-Control-Max-Age 标题值。
证书
如果设置了省略凭证标志,则返回false,否则返回true。
方法
如果标题不为空,则为空; 否则Access-Control-Allow-Methods 标题中的一个值
如果方法不为空,则为空; 否则Access-Control-Allow-Headers 标题中的一个值

需要明确的是,方法标题字段是互斥的。当其中一个是空的时,另一个是非空的。

条目的主键包括除max-age字段之外的所有字段

自存储条目以来,在max-age字段中指定的时间过后,必须删除条目。还可以根据以下算法添加和删除条目。它们的添加和删除方式使缓存中永远不会有重复的项目。

用户代理可以在max-age字段中指定的时间之前清除缓存条目

虽然这有效地使 预检结果缓存可选,但强烈建议用户代理支持它。

7.1.7通用跨源请求算法

通用步骤集中使用的变量是调用这些步骤的算法的一部分。


每当作出步骤的请求被施加, 请求URL原点 源来源使用 引荐源作为覆盖引荐源手动重定向标记组,以及 块饼干标志,如果设置 省略凭证标志被设置。使用方法 请求方法,实体主体请求实体主体,包括作者请求标头如果未设置省略凭证标志,包括 用户凭证

每当应用重定向步骤时,请执行以下步骤:

  1. 原始URL成为请求URL

  2. 请求URLURL由输送Location中的重定向响应报头。

  3. 如果不支持请求URL <scheme>,则违反了无限循环预防措施,或者用户代理由于某些其他原因而不希望发出新请求,请应用 网络错误步骤

  4. 如果请求URL包含 userinfo生产应用 网络错误步骤

  5. 如果当前资源资源共享检查失败,请应用网络错误步骤

  6. 如果请求URL 原点是不 相同的来源原始URL 原点,设定 源原点到一个全局唯一标识符(变为“ null”发送时)。

  7. 在观察请求规则集的同时,透明地遵循重定向


每当应用中止步骤时,终止调用此组步骤的算法并将 跨源请求状态设置中止错误


每当 应用网络错误步骤时,终止调用此组步骤的算法并将跨源请求状态设置网络错误

这对用户凭据的设置没有影响 即如果未设置阻止cookie标志 ,则响应将设置cookie。

每当应用 缓存和网络错误步骤 时,请按照下列步骤操作:

  1. 删除预检结果缓存的条目,其中origin字段值是源origin区分大小写的匹配项url字段值是请求URL区分大小写的匹配项

  2. 应用网络错误步骤,就好像调用缓存的算法和网络错误步骤 调用网络错误步骤一样


预检结果缓存中有一个缓存条目时,会有一个 缓存匹配 ,其满足以下条件:

有一种 方法缓存匹配 时,有一个高速缓存条目为其中有一个高速缓存匹配方法字段值是 大小写敏感的用于给定方法的匹配。

有一个 头缓存的比赛 时,有一个缓存条目其中有一个缓存匹配字段的值是一个 ASCII不区分大小写为给定的头字段名称相匹配。

7.2资源共享检查

给定资源资源共享检查算法如下:

  1. 如果响应包含零个或多个 Access-Control-Allow-Origin 标头值,则返回失败并终止此算法。

  2. 如果 Access-Control-Allow-Origin 标头值是“ *”字符并且设置了 省略凭证标志,则返回pass并终止该算法。

  3. 如果值 Access-Control-Allow-Origin 不是由其规范定义标头值的区分大小写匹配 Origin,则返回失败并终止此算法。

  4. 如果未设置省略凭证标志且响应包含零个或多个 Access-Control-Allow-Credentials 标头值,则返回失败并终止此算法。

  5. 如果未设置省略凭证标志Access-Control-Allow-Credentials 标头值不是区分大小写匹配true,则返回失败并终止此算法。

  6. 回传。

当源的ASCII序列化为字符串“ null时,上述算法也起作用

7.3安全

本节不具有规范性。

在不同的地方,用户代理可以采取额外的预防措施。例如,允许用户代理不存储缓存项,在缓存项达到其最大年龄之前删除它们 ,并且不连接到某些 URL

鼓励用户代理对max-age施加限制, 因此项目不能在 预检结果缓存中停留不合理的时间。

跨源请求 算法的第一步所示,并且在重定向步骤算法中,允许用户代理终止算法而不发出请求。这可以做到,因为例如:

鼓励用户代理在通用级别上应用安全性决策,而不仅仅是资源共享策略。例如,如果用户代理不允许从请求httpshttp 在同一个方案跨来源请求它鼓励为HTML做同样的img元件。

8 CORS API规范建议

本节不具有规范性。

此规范定义了资源共享策略,如果没有使用它的API,则无法实现该策略。定义使用该策略的API的规范是CORS API规范。

如果CORS API规范定义了多个使用该策略的API,则应为每个API单独考虑建议。

8.1构建跨源请求

对于API可以为此规范中的资源共享策略应用的所有跨源请求,CORS API规范需要引用 跨源请求算法并适当地设置以下输入变量:请求URL请求方法作者请求标题请求实体主体源来源手动重定向标志省略凭证标志强制预检标志

允许CORS API规范让这些输入变量由API控制,但也可以设置固定值。

API的CORS API规范仅允许使用该GET方法的请求GET可以将请求方法设置 请求实体主体为空,并将源来源设置 为某个适当的值,并让其他变量由API控制。

8.2处理跨源重定向的同源

由于浏览器基于 相同的原始安全模型,并且本规范中概述的策略适用于浏览器中使用的API,因此预计将利用此策略的API将必须处理导致重定向相同源请求。以特殊方式交叉起源

对于透明地处理重定向的API,鼓励CORS API规范透明地“捕获”重定向并在(跨源)重定向URL 调用跨源请求算法来透明地处理此场景

XMLHttpRequest规范执行此操作。 [XHR]

8.3处理跨源请求状态

跨源请求正在进行时,其相关的跨源请求状态被更新。根据跨源请求状态的值,API将以不同的方式做出反应:

预检完成

现在可以启用预检请求后才能安全曝光的 功能。

例如,上传进度事件 XMLHttpRequest

成功

响应的内容可以与API共享,包括尚未过滤的标头。

请求本身仍然可以进展。即, 跨源请求状态值不表示请求已完成。

中止错误

处理类似于用户中止请求的请求。这可以与处理网络错误的方式等效地处理。确保不要透露有关请求的任何进一步信息。

网络错误

处理类似于发生某种错误的请求。确保不透露有关请求的任何进一步信息。

8.4安全

相同的源请求类似,鼓励CORS API规范正确限制作者可以为跨源请求设置和获取的标头,方法和用户凭据

查看XMLHttpRequest规范为要施加的限制提供了良好的开端。 [XHR]

CORS API规范还需要确保在跨源请求状态设置为 预检完成成功以防止例如端口扫描之前不显示任何内容

在XMLHttpRequest中,仅在跨源请求状态设置为 成功后才调度进度事件仅当跨源请求状态预检完成时,才会调度上载进度事件

参考

[困惑]
(非规范性)困惑的副手,Norm Hardy。
[饼干]
AdamState Management Mechanism,Adam Barth。IETF。
[CSRF]
(非规范性)跨站请求伪造,彼得沃特金斯。
[EventSource的]
(非规范性)服务器发送事件,Ian Hickson。W3C。
[HTML]
HTML5,Berjon,Leithead,Navara,O'Connor,Pfeiffer和Hickson。W3C。
[HTTP]
超文本传输​​协议 - HTTP / 1.1,Roy Fielding,James Gettys,Jeffrey Mogul等人.IETF。
[308]
超文本传输​​协议(HTTP)状态代码308(永久重定向),Julian Reschke。IETF。
[JSONP]
(非规范)JSONP,Bob Ippolito。
[OAUTH]
(非规范性)OAuth 1.0协议,Eran Hammer-Lahav。IETF。
[起源]
网络起源概念,Adam Barth。IETF。
[RFC2119]
关键词在RFC中用于表明需求水平,Scott Bradner。IETF。
[URI]
统一资源标识符(URI):通用语法,Tim Berners-Lee,Roy Fielding和Larry Masinter。IETF。
[XHR]
(非规范性)XMLHttpRequest,Anne van Kesteren。W3C。

致谢

本附录是非规范性的。

编辑要感谢Adam Barth,Alexey Proskuryakov,Arne Johannessen,Arthur Barstow,Benjamin Hawkes-Lewis,Bert Bos,BjörnHöhrmann,Boris Zbarsky,Brad Hill,Cameron McCormack,Collin Jackson,DavidHåsäther,David Orchard,Dean Jackson, Eric Lawrence,Frank Ellerman,Frederick Hirsch,Graham Klyne,Hal Lockhart,Henri Sivonen,Ian Hickson,Jesse M. Heines,Jonas Sicking,Julian Reschke,Lachlan Hunt,吕康豪(Kang-Hao Lu),Maciej Stachowiak,Marc Silbey,Marcos Caceres,Mark Nottingham,Mark S. Miller,MartinDürst,Matt Womer,Mhano Harkness,Michael Smith,Mohamed Zergaoui,Nikunj Mehta,OdinHørtheOmdal,PhilipJägenstedt,Sharath Udupa,Simon Pieters,Sunava Dutta,Surya Ismail,Thomas Roessler, Tyler Close,Jeff Hodges,Vladimir Dzhuvinov,Wayne Carr和Zhenbin Xu对本规范的贡献。

特别感谢Brad Porter,Matt Oshry和R. Auburn,他们都帮助编辑了本文档的早期版本。