有效Cookie值的权威指南

时间:2011-05-24 09:13:11

标签: java http

我知道还有其他问题,但他们似乎有一些假设而不是明确的答案。

我有限的理解是cookie值是:

  • 分号已用于分隔单个Cookie中的Cookie属性。
  • 等号用于分隔cookie名称和值
  • 冒号用于分隔标题中的多个Cookie。

还有其他“特殊”字符吗?

其他一些q / a建议一个base64对值进行编码,但这当然可能包括等于当然无效的等号。

我也看到了一些建议,可能会引用这些值,但会导致其他问题。

  • 需要引用特殊字符吗?
  • 引用的值支持通常的反斜杠转义机制。

RFC 我读了一些RFC,包括许多cookie RFCS中的一些,但我仍然不确定是否存在对另一个RFC等的交叉引用,没有明确的简单解释或样本“回答”我的查询。

希望没有人会说阅读RFC,因为问题变成了哪个RFC ......

我想我也读过不同的浏览器规则略有不同,所以如果这很重要,请在答案中注明。

2 个答案:

答案 0 :(得分:21)

最新的RFC是6265,它声明以前的Cookie RFC已经过时。

以下是RFC中的语法规则:

 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

因此:

  • 特殊字符是空格字符,双引号,逗号,分号和反斜杠。等于不是一个特殊的角色。

  • 根本不能使用特殊字符,但双引号可以包围该值。

  • 不能引用特殊字符。

  • 反斜杠不是逃避。

因此可以使用base-64编码,因为equals不是特殊的。

最后,据我所知,RFC 6265 cookie值已定义,以便它们可以与任何实现任何Cookie RFC的浏览器一起使用。但是,如果您尝试使用不符合RFC 6265的cookie值(但可以证明符合早期的RFC),您可能会发现cookie行为因浏览器而异。

简而言之,请遵守RFC 6265的字母,你应该没问题。

答案 1 :(得分:0)

提到了base64,所以这里是一个使用cookies的熟饼干解决方案。这些函数是关于base64的修改版本,它们只使用[0-9a-zA-Z _-]

你可以将它用于cookie的名称和值部分,就像他们所说的那样是二进制安全的。

gzdeflate / gzinflate占用了base64创建的大约30%的空间,无法抗拒使用它。请注意,php gzdeflate / gzinflate仅适用于大多数托管公司,而不是全部。

//write
setcookie
         (
         'mycookie'
         ,code_base64_FROM_bytes_cookiesafe(gzdeflate($mystring))
         ,time()+365*24*3600
         );
//read
$mystring=gzinflate(code_bytes_FROM_base64_cookiesafe($_COOKIE['mycookie']));


function code_base64_FROM_bytes_cookiesafe($bytes)
    {
    //safe for name and value part [0-9a-zA-Z_-]
    return strtr(base64_encode($bytes),Array
            (
            '/'=>'_',
            '+'=>'-',
            '='=>'',
            ' '=>'',
            "\n"=>'',
            "\r"=>'',
            ));
    }


function code_bytes_FROM_base64_cookiesafe($enc)
    {
    $enc=str_pad($enc,strlen($enc)%4,'=',STR_PAD_RIGHT);//add back =
    $enc=chunk_split($enc);//inserts \r\n every 76 chars
    return base64_decode(strtr($enc,Array
            (
            '_'=>'/',
            '-'=>'+',
            )));
    }