【问题标题】:Should packed cookies be treated as a single cookie?包装好的饼干是否应该被视为一个单独的饼干?
【发布时间】:2016-09-30 00:02:05
【问题描述】:

我看到一些网站,比如 stackoverflow,使用打包的 cookie,将多个 cookie 打包成一个。这是一个例子:

设置-Cookie:acct=t=&s=;域=.stackapps.com;过期=格林威治标准时间 2016 年 5 月 30 日星期一 20:16:22;路径=/; HttpOnly

这是否只是为了节省发送多个 set-cookie 标头,并避免在一个 set-cookie 标头上发送逗号分隔的 cookie?这是允许的——但不建议这样做吗?

打包后的 cookie 应该被视为单个 cookie,还是需要解包并作为单独的 cookie 发回?

【问题讨论】:

    标签: http cookies http-headers


    【解决方案1】:

    我不知道“打包”的想法是从哪里来的。这些只是值中带有= 符号的cookie,或者至少应该符合规范。让我们浏览一下 RFC,看看:

    Set-Cookie: acct=t=&s=; domain=.stackapps.com; expires=...
    

    完全一样

    Set-Cookie: acct="t=&s="; domain=.stackapps.com; expires=...
    

    因此,它是一个单一的 cookie,应该被这样对待。

    答案很长,抱歉。我试图针对那些发现 RFC 中的语法规则难以理解的人。如果您认为某些语法仍然难以理解,请在评论中指出。


    通过 RFC

    Set-Cookie 标头的当前 RFC 是 RFC6265,在 4.1 部分它具有 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 ";">
    

    这有点简洁,但我们不需要全部完成。首先,我们有 Set-Cookie: 标头和一个空格 (SP),然后是进一步定义的 set-cookie-string

    set-cookie-header = "Set-Cookie:" SP set-cookie-string
    

    set-cookie-stringcookie-pair(进一步定义)组成,这是我们感兴趣的语法部分,以及可选的一组任意数量的cookie-av,前缀为;和一个空格。 *() 构造允许语法部分出现任意次数(包括零次)。

    set-cookie-string = cookie-pair *( ";" SP cookie-av )
    

    cookie-av 定义了可以在 cookie 中使用但我们的证明不需要的元数据,因此我们将放弃讨论。

    另一方面,cookie-pair 是一个非常简单的结构:一个cookie-name 一个强制 = 符号和一个cookie-value

    cookie-pair       = cookie-name "=" cookie-value
    

    cookie-name 被定义为 token,这将我们引向另一个 RFC,RFC2616。在该 RFC 的 2.2 部分中,我们找到了定义 token 的基本规则。

    cookie-name       = token
    token             = <token, defined in [RFC2616], Section 2.2>
    

    token 定义:

    CTL            = <any US-ASCII control character
                     (octets 0 - 31) and DEL (127)>
    ...
    token          = 1*<any CHAR except CTLs or separators>
    separators     = "(" | ")" | "<" | ">" | "@"
                   | "," | ";" | ":" | "\" | <">
                   | "/" | "[" | "]" | "?" | "="
                   | "{" | "}" | SP | HT
    

    1*&lt;&gt; 语法表示出现次数不限,但至少出现一次。要查找CTLs,请使用man ascii 并检查Dec 列,SP 是空格(正如我们已经看到的),HT 是水平制表符(ascii 表中的9)。

    对我们来说有趣的部分是token 不能包含= 字符

    回到 RFC6265:

    cookie-pair       = cookie-name "=" cookie-value
    

    cookie-name 在第一个 = 字符处停止,第一个 = 字符始终是语法中的 = 显式。现在,让我们最终定义cookie-value

    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
    

    我们已经看到那里的* 表示任何出现,包括零(请注意,RFC 允许空 cookie!)。整个cookie-value 有趣的部分可以用双引号括起来(DQUOTE 是您可能已经猜到的双引号字符)。

    但最有趣的部分是= 符号(ascii 中的x3D)表允许作为cookie-octet

    / %x3C-5B / <- right there!
    

    但不允许使用空格 (x20) 和分号 (x3B)。

    结论

    因此,Set-Cookie 标头应解释为

    Set-Cookie: acct=t=&s=; domain=.stackapps.com; expires=...
    
    cookie-set-header = "Set-Cookie:" SP set-cookie-string
    set-cookie-string = cookie-pair *(";" cookie-av)
    cookie-pair       = cookie-name "=" cookie-value
    cookie-name       = "acct"
    cookie-value      = "t=&s="
    

    并且将其发送回服务器的标头应为

    Cookie: acct=t=&s=
    

    如下发送违反了 RFC

    Cookie: acct=t&; s=
    

    【讨论】:

    猜你喜欢
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 2016-03-21
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多