4. Server Requirements (服务器要求)
本节描述了Cookie和Set-Cookie头部的良好行为配置文件的语法和语义。
4.1. Set-Cookie
Set-Cookie HTTP响应头用于从服务器向用户代理发送cookies。
4.1.1. 语法 (Syntax)
非正式地说,Set-Cookie响应头包含头名称"Set-Cookie",后跟":"和一个cookie。每个cookie以名称-值对开始,后跟零个或多个属性-值对。服务器不应该 (SHOULD NOT) 发送不符合以下语法的Set-Cookie头:
set-cookie-header = "Set-Cookie:" SP set-cookie-string
set-cookie-string = cookie-pair *( ";" SP cookie-av )
cookie-pair = cookie-name "=" cookie-value
cookie-name = token
cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
; US-ASCII字符,排除CTL、
; 空白、DQUOTE、逗号、分号
; 和反斜杠
token = <token, 在[RFC2616]第2.2节中定义>
cookie-av = expires-av / max-age-av / domain-av /
path-av / secure-av / httponly-av /
extension-av
expires-av = "Expires=" sane-cookie-date
sane-cookie-date = <rfc1123-date, 在[RFC2616]第3.3.1节中定义>
max-age-av = "Max-Age=" non-zero-digit *DIGIT
; 实际上,expires-av和max-age-av
; 都限制于用户代理可表示的日期
non-zero-digit = %x31-39
; 数字1到9
domain-av = "Domain=" domain-value
domain-value = <subdomain>
; 在[RFC1034]第3.5节中定义,
; 由[RFC1123]第2.1节增强
path-av = "Path=" path-value
path-value = <除CTL或";"之外的任何CHAR>
secure-av = "Secure"
httponly-av = "HttpOnly"
extension-av = <除CTL或";"之外的任何CHAR>
请注意,上述一些语法术语引用了使用与本文档(使用[RFC5234]的ABNF)不同语法表示法的文档。
cookie-value的语义未由本文档定义。
为了最大化与用户代理的兼容性,希望在cookie-value中存储任意数据的服务器应该 (SHOULD) 对该数据进行编码,例如使用Base64 [RFC4648]。
由cookie-av项生成的set-cookie-string部分称为属性。为了最大化与用户代理的兼容性,服务器不应该 (SHOULD NOT) 在同一个set-cookie-string中生成两个同名的属性。(有关用户代理如何处理这种情况,请参见第5.3节。)
服务器不应该 (SHOULD NOT) 在同一响应中包含多个具有相同cookie-name的Set-Cookie头字段。(有关用户代理如何处理这种情况,请参见第5.2节。)
如果服务器向用户代理并发发送包含Set-Cookie头的多个响应(例如,当通过多个套接字与用户代理通信时),这些响应会创建"竞态条件",可能导致不可预测的行为。
注意:一些现有的用户代理在解释两位数年份时存在差异。为了避免兼容性问题,服务器应该 (SHOULD) 使用rfc1123-date格式,该格式需要四位数年份。
注意:一些用户代理将cookies中的日期存储和处理为32位UNIX time_t值。某些系统上支持time_t处理的库中的实现错误可能导致此类用户代理错误地处理2038年之后的日期。
4.1.2. 语义(非规范性)(Semantics - Non-Normative)
本节描述Set-Cookie头的简化语义。这些语义足够详细,可用于理解服务器最常见的cookies使用方式。完整的语义在第5节中描述。
当用户代理收到Set-Cookie头时,用户代理会将cookie及其属性一起存储。随后,当用户代理发起HTTP请求时,用户代理会在Cookie头中包含适用的、未过期的cookies。
如果用户代理收到一个新cookie,其cookie-name、domain-value和path-value与已存储的cookie相同,则现有cookie将被驱逐并替换为新cookie。请注意,服务器可以通过向用户代理发送具有Expires属性值在过去的新cookie来删除cookies。
除非cookie的属性另有说明,否则cookie仅返回给源服务器(例如,不返回给任何子域),并在当前会话结束时过期(由用户代理定义)。用户代理会忽略无法识别的cookie属性(但不会忽略整个cookie)。
4.1.2.1. Expires属性 (The Expires Attribute)
Expires属性表示cookie的最大生存期,表示为cookie过期的日期和时间。用户代理不需要将cookie保留到指定日期过去。实际上,由于内存压力或隐私问题,用户代理经常驱逐cookies。
4.1.2.2. Max-Age属性 (The Max-Age Attribute)
Max-Age属性表示cookie的最大生存期,表示为cookie过期前的秒数。用户代理不需要在指定的持续时间内保留cookie。实际上,由于内存压力或隐私问题,用户代理经常驱逐cookies。
注意:一些现有的用户代理不支持Max-Age属性。不支持Max-Age属性的用户代理会忽略该属性。
如果cookie同时具有Max-Age和Expires属性,则Max-Age属性优先并控制cookie的过期日期。如果cookie既没有Max-Age也没有Expires属性,则用户代理将保留cookie直到"当前会话结束"(由用户代理定义)。
4.1.2.3. Domain属性 (The Domain Attribute)
Domain属性指定将向哪些主机发送cookie。例如,如果Domain属性的值为"example.com",则用户代理在向example.com、www.example.com和www.corp.example.com发起HTTP请求时将在Cookie头中包含该cookie。(请注意,前导%x2E (".")(如果存在)会被忽略,即使不允许该字符,但尾随%x2E (".")(如果存在)将导致用户代理忽略该属性。)如果服务器省略Domain属性,则用户代理仅将cookie返回给源服务器。
警告:一些现有的用户代理将缺少的Domain属性视为存在Domain属性并包含当前主机名。例如,如果example.com返回不带Domain属性的Set-Cookie头,这些用户代理也会错误地将cookie发送到www.example.com。
用户代理将拒绝cookies,除非Domain属性为cookie指定了包括源服务器的范围。例如,用户代理将接受来自foo.example.com的Domain属性为"example.com"或"foo.example.com"的cookie,但用户代理不会接受Domain属性为"bar.example.com"或"baz.foo.example.com"的cookie。
注意:出于安全原因,许多用户代理配置为拒绝对应于"公共后缀"的Domain属性。例如,一些用户代理将拒绝"com"或"co.uk"的Domain属性。(有关更多信息,请参见第5.3节。)
4.1.2.4. Path属性 (The Path Attribute)
每个cookie的范围限制为一组路径,由Path属性控制。如果服务器省略Path属性,则用户代理将使用request-uri路径组件的"目录"作为默认值。(有关更多详细信息,请参见第5.1.4节。)
用户代理仅当请求uri的路径部分匹配(或是...的子目录)cookie的Path属性时,才会在HTTP请求中包含该cookie,其中%x2F ("/")字符被解释为目录分隔符。
尽管看似可用于在给定主机内的不同路径之间隔离cookies,但不能依赖Path属性来提供安全性(请参见第8节)。
4.1.2.5. Secure属性 (The Secure Attribute)
Secure属性将cookie的范围限制为"安全"通道(其中"安全"由用户代理定义)。当cookie具有Secure属性时,用户代理仅当请求通过安全通道传输时(通常是通过传输层安全性的HTTP (TLS) [RFC2818]),才会在HTTP请求中包含该cookie。
尽管看似可用于保护cookies免受活跃网络攻击者的攻击,但Secure属性仅保护cookie的机密性。活跃的网络攻击者可以从不安全的通道覆盖Secure cookies,从而破坏其完整性(有关更多详细信息,请参见第8.6节)。
4.1.2.6. HttpOnly属性 (The HttpOnly Attribute)
HttpOnly属性将cookie的范围限制为HTTP请求。特别是,该属性指示用户代理在通过"非HTTP" API(例如向脚本公开cookies的Web浏览器API)提供对cookies的访问时省略该cookie。
请注意,HttpOnly属性与Secure属性是独立的:cookie可以同时具有HttpOnly和Secure属性。
4.2. Cookie
4.2.1. 语法 (Syntax)
用户代理在Cookie头中向源服务器发送存储的cookies。如果服务器符合第4.1节中的要求(并且用户代理符合第5节中的要求),则用户代理将发送符合以下语法的Cookie头:
cookie-header = "Cookie:" OWS cookie-string OWS
cookie-string = cookie-pair *( ";" SP cookie-pair )
4.2.2. 语义 (Semantics)
每个cookie-pair表示用户代理存储的一个cookie。cookie-pair包含用户代理在Set-Cookie头中接收的cookie-name和cookie-value。
请注意,不返回cookie属性。特别是,服务器无法仅从Cookie头确定cookie何时过期、cookie对哪些主机有效、cookie对哪些路径有效,或者cookie是否使用Secure或HttpOnly属性设置。
Cookie头中各个cookies的语义未由本文档定义。服务器应该为这些cookies赋予特定于应用程序的语义。
尽管cookies在Cookie头中以线性方式序列化,但服务器不应该 (SHOULD NOT) 依赖序列化顺序。特别是,如果Cookie头包含两个同名的cookies(例如,使用不同的Path或Domain属性设置的),服务器不应该 (SHOULD NOT) 依赖这些cookies在头中出现的顺序。