来自:RFC6265
(Abstract)摘要:
本文当定义了HTTP Cookie 和 Set-Cookie消息头。HTTP服务器可以在HTTP 用户代理(HTTP user agents)上保存状态,以便服务器在无状态的HTTP协议之上维护有状态的会话。虽然cookie的一些历史遗留问题导致了其较低的安全性和隐私性,但是Cookie和Set-Cookie消息头在Internet上仍旧被广泛的使用着。
1.(Introduction)简介:
本文当定义了HTTP Cookie 和 Set-Cookie消息头。利用Set-Cookie消息头,HTTP服务器(HTTP Server)可以向用户代理(user agents)传送多个name/value以及相关的元数据(称为cookies),用户代理接下来向服务器发送请求时,可以利元数据和其它一些信息来决定是否要将这些name/vlaue对在Cookie消息头中返回至服务器。
虽然表面上看起来简单,但是cookies却有诸多复杂性。例如,服务器会为每一下发送到用户代理的cookie指定一个作用域。该作用域指定了用户代理应该返回cookie的最大时间段,用户代理要将cookie发送到哪个服务器,以及cookie所接受的URI语义。
用于历史原因,cookies包含许多安全和隐私问题。例如,一台服务器指出某个cookie是“安全的”,但该安全属性在一个积极的网络攻击者面前却并没有提供完整性。同样,指定主机下的cookie在会在该主机的所有端口上共享,尽管浏览器通常会利用同源策略将获取的内容在不同的端口上进行隔离。
3.(Overview)概要:
本节勾画了一台源服务器向用户代理发送状态信息,以及用户代理向源服务器返回这些状态信息的方式。
为了保存状态,源服务器在一个HTTP 响应中包含进Set-Cookie消息头。在接下来的请求中,用户代理会将Cookie请求头返回给服务器。Cookie消息头中包含了用户代理先前收到的通过Set-Cookie消息头来设置的cookie。源服务器可以自由选择是忽略Cookie消息头,还是为了应用程序预定义目的来使用其内容。
源服务器可以在任意的响应中设置Set-Cookie响应头。
用户代理可以忽略状态码为100的响应中包含的Set-Cookie消息头,但是必须处理其它响应中包含的Set-Cookie消息头(包括状态码为400,500的响应)。源服务器可以在单一响应中包含多个Set-Cookie消息头。Cookie和Set-Cookie消息头的存在不会阻碍HTTP缓存的存储以及响应的重用。
3.1.(Examples) 样例
利用Set-Cookie消息头,服务器可以在一个HTTP响应中向用户代理发送一个简短的字符串,用户代理之后可以在符合cookie作用域下的请求中返回该字符串。例如,服务器可以向用户代理发送一个名为SID的“会话标识(session identifier)”,该标识的值为31d4d96e407aad42。用户代理可以在之后请求中将该sid返回给服务器。
== Server -> User Agent == Set-Cookie: SID=31d4d96e407aad42 == User Agent -> Server == Cookie: SID=31d4d96e407aad42
服务器可以利用Path和Domain属性来更改Cookie的作用域。例如,服务器可以通知用户代理将该cookie返回给exemple.com下的所有路径和所有子域。
== Server -> User Agent == Set-Cookie: SID=31d4d96e407aad42; Path=/; Domain=example.com == User Agent -> Server == Cookie: SID=31d4d96e407aad42
在接下来的样例展示中,服务器可以在用户代理中储存多个cookies。例如,服务器通过两个Set-Cookie来存储SID和用户的首选语言。注意服务器利用Secure和HttpOnly属性为多数敏感的SID提供安全保护。
== Server -> User Agent == Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly Set-Cookie: lang=en-US; Path=/; Domain=example.com == User Agent -> Server == Cookie: SID=31d4d96e407aad42; lang=en-US
请注意以上Cookie的消息头中包含了两个cookies,一个叫SID,一个叫lang。如果服务器希望用户代理在多个“会话”中保存该cookie,那么服务器可以在Expires属性中指定一个失效日期。要注意的是用户代理可能在这个失效日期之前删除该cookie,如果用户代理的cookie存储超出了上限或者如果用户手工删除了服务器的cookie。
== Server -> User Agent == Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT == User Agent -> Server == Cookie: SID=31d4d96e407aad42; lang=en-US
最后,要删除cookie的话,服务器可以返回一个失效日期为过去某个时间点的Set-Cookie消息头。但是同时只有
Set-Cookie消息头中包含的Path和Domain属性,与cookie创建时保存的这两个属性一致时,服务器才能成功将其删除。
== Server -> User Agent == Set-Cookie: lang=; Expires=Sun, 06 Nov 1994 08:49:37 GMT == User Agent -> Server == Cookie: SID=31d4d96e407aad42
4.(Server Requirements)服务器要求
本节描述了Cookie和Set-Cookie消息头的语法和语义概要。
4.1.Set-Cookie
Set-Cookie HTTP响应消息头被服务器用来向用户代理发送cookies.
4.1.1.(Syntax)语法
简略的来说,Set-Cookie响应消息中包含了一个名为“Set-Cookie”的消息头,后跟一个“:”以及一个cookie。每个cookie都以一个名称-值对(name-value-paris)开始,后跟零个或多个属性-值对(attribute-value).服务器在发送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 characters excluding CTLs, ; whitespace DQUOTE, comma, semicolon, ; and backslash token = <token, defined in [RFC2616], Section 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, defined in [RFC2616], Section 3.3.1> max-age-av = "Max-Age=" non-zero-digit *DIGIT ; In practice, both expires-av and max-age-av ; are limited to dates representable by the ; user agent. non-zero-digit = %x31-39 ; digits 1 through 9 domain-av = "Domain=" domain-value domain-value = <subdomain> ; defined in [RFC1034], Section 3.5, as ; enhanced by [RFC1123], Section 2.1 path-av = "Path=" path-value path-value = <any CHAR except CTLs or ";"> secure-av = "Secure" httponly-av = "HttpOnly" extension-av = <any CHAR except CTLs or ";">
注意cookie-value的语义在本文档中没有定义。
为了兼容更广泛的用户代理,想要在cookie-value中存储任意数据的服务器,需要对数据进行编码,例如,利用Base64[RFC4648]。
set-cookie-string中由cookie-av组成的部分通常被称为属性。为了兼容最广泛的用户代理。服务器不应该在一个同一个set-cookie-string中产生两个同名的属性名(Setion5.3)讲解了用户代理对这种情况的处理)。
服务器不应该在一个响应中向用户代理发送包含多个具有相同的cookie-name的Set-Cookie消息头。(Section5.2中讲解了用户代理是如何处理这种情况)。
4.1.2 .Semantics(Non-Normative)语义(非标准的)
本节描述了Set-Cookie消息头的简要意义。这些语义对于理解服务器是如何利用cookie的来说已经足够详细。全部的语义在Section5中描述。
当用户代理收到了一个Set-Cookie消息头时,用户代理会将cookie以及它的属性一起进行存储。接下来,当用户代理发送一个HTTP请求时,用户代理会将合适的,没有过期的cookies包含在Cookie消息头中。
如果用户代理收到了一个cookie,并且与当前存储的cookie具有相同的cookie-name,domain-value以及path-value,已存在的cookie会被销毁并被新的cookie替换。注意服务器可以通过向用户代理发送新的cookie来删除cookie,只要新的cookie中包含以过去某个时间为值的Expires 属性。
除非cookie的属性名且指明,否则cookie只会返回给远服务器(并不会返回值任何子域下的服务器),并且在当前会话结束或过期。用户代理会忽略无法识别的cookie属性。
4.1.2.1 . Expires属性
Expires属性标明了cookie的最大生命期,以日期和时间的形式代表了cookie的失效期。用户代理不必保留cookie直到其指定的时间已经过去。事实上,用户代理通常会因为内存空间限制和隐私性考虑,而将cookie删除。
4.1.2.2. Max-Age属性
Max-Age属性标明了cookie的最大生命期,以毫秒数值形式代表了cookie的失效期。用户代理不必在一段时间内保留cookie。事实上用户代理通常会因为内存空间限制和隐私性考虑,而将其删除。
注意:一些用户代理不支持Max-Age属性。不支持该属性的用户代理会将其忽略掉。
如果一个Cookie同时拥有Max-Age属性和Expires属性,那么Max-Age属性会优先并且控制了Cookie的失效日期。如果cookie既没有Max-Age属性,也没有Expires属性,那么用户代理只会保存cookie直至当前会话失效。
4.1.2.3 Domain属性
Domain属性指明了cookie将会被发送至哪个域下。例如,如果Domain属性的值是“example.com”,用户代理会在向example.com,www .example.com www.corp.example,com 发送的请求的Cookie消息头中包含cookie。如果服务器在cookie的设置中省略Domain属性,那么用户代理只会向源服务器发送cookie。
注意:一些已有的用户代理会将缺少Domain属性以当前域名为值进行补齐。例如,如果example.com返回了一个没有Domain属性的Set-Cookie消息头,这些用户代理会同样错误的将cookie发送到www.example.com 中。
用户代理会忽略那些没有在Domain属性中指明源服务器的cookie。例如用户代理会接受来自foo.example.com的,Domain属性值为example.com,或foo.example.com的cookie。但是会拒绝Domain值为bar.example.com或baz.foo.example.com的cookie。
注意,处于安全原因,许多用户代理会进行配置以拒绝那些Domain属性与“公共后缀”相对应的cookie。例如。一些用户代理会忽略Domain属性包含“com”,或“co.uk”的cookie。
4.1.2.4. Path属性
每个cookie的作用域都限定在一个路径集合中,这些是通过Path属性进行设置的。如果服务器省略path属性,用户代理会利用request-uri中的path组件部分对应的目录来作为其默认值.
当HTTP请求的request-uri中的path部分与cookie中的Path属性相匹配(或是Path的子目录)时,用户代理会在该请求中包含cookie,"/"会被解析为目录分隔符。
虽然貌似在一个指定域中的不同的path下将cookie进行了有效的隔离,但是不能完全依赖Path属性来用于安全性。
4.1.2.5. Secure属性
Secure属性限定cookie的作用域为"Secure"隧道("Secure"在用户代理中进行定义)。当一个cookie拥有Secure属性,用户代理只有在HTTP请求在secure隧道上传输时,才会包含cookie,
4.1.2.6. HttpOnly属性
HttpOnly属性限定了cookie的作用域只适用于HTTP请求。尤其,该属性告之用户代理当通过“Non-Http”APIS访问cookies时要省略cookie
注意HttpOnly属性独立于Secure属性:一个Cookie可以同时拥有HttpOnly属性和Secure属性。
4.2. Cookie
4.2.1. 语法
用户代理会在Cookie消息头中向源服务器发送已存储的cookies。吐过服务器满足4.1节的条件(并且用户代理满足5节中的条件),用户大力会以符合以下语法规则来发送Cookie消息头。
cookie-header = "Cookie:" OWS cookie-string OWS cookie-string = cookie-pair *( ";" SP cookie-pair )
4.2.2. 语义
每一个cookie对(cookie-pair)都代表了一个用户代理已存储的cookie。cookie对(cookie-pair)包含用户代理在Set-Cookie中获取的cookie-name和cookie-value。
需要注意的是cookie的所有属性不会被返回值服务器。尤其,服务器不能从Cookie消息头中决定什么时候cookie会失效,该cookie对于哪个域是有效的,该cookie对于哪个路径是有效的,或者该cookie是否包含了Secure属性或HttpOnly属性。
每个包含在Cookie消息头中的单独cookie的语义没有在本文档中定义。服务器需要对这些cookie冠以与特性应用相关的语义。
虽然cookies在Cookie消息头中以线性方式序列化,但是服务器不应该依赖于这些序列化的顺序。尤其当Cookie消息头中包含了两个同名的不同的cookies(例如,以不同Path或Domain值设置的cookie),服务器不能依赖于cookies在消息头中出现的顺序。
注:本文只对该文档的<1>,<3>,<4>做了简单的翻译,因为这三节主要介绍了cookie的原理和简单的描述,全文一共10节,第二节,描述了文档的术语约定,第五节主要讲解的是Cookie实现的一些算法要求和Set-Cookie消息头属性的介绍。第六节说明了一些cookie实现的考虑问题。第七、八节描述了Cookie的隐私性和安全性,有兴趣大家可以细看!本文翻译难免有些生硬,而且在该三节中也省略了一些自己弄不明白的东西,对于全面的介绍,还是要参考原文档!