我正在考虑放弃 PHP 的$_SESSION
(即服务器端会话处理,为了添加一些与语言无关的味道),改为使用签名的 cookie,因为我听到了许多好消息(Flickr 使用它们,所以它们应该对我也足够好)。
我理解这个技术的基本内容:自由使用Cookie将键值对从客户端传递到服务器,并对其进行签名以确保值没有被篡改。
但是,实现签名部分的好方法是什么?此外;由于交通可能是HTTP,是否有一种好的方法可以使用此方法发送敏感数据(例如用户的密码),同时防止cookie盗用和/或篡改?
我正在考虑放弃 PHP 的$_SESSION
(即服务器端会话处理,为了添加一些与语言无关的味道),改为使用签名的 cookie,因为我听到了许多好消息(Flickr 使用它们,所以它们应该对我也足够好)。
我理解这个技术的基本内容:自由使用Cookie将键值对从客户端传递到服务器,并对其进行签名以确保值没有被篡改。
但是,实现签名部分的好方法是什么?此外;由于交通可能是HTTP,是否有一种好的方法可以使用此方法发送敏感数据(例如用户的密码),同时防止cookie盗用和/或篡改?
我不会在敏感数据中使用这种技术。但如果与常规会话结合使用,它可以非常有用——您可以为客户提供一个具有普通会话ID的cookie,但也包括您的应用程序在每个页面上需要的所有键/值对。这样,您就可以避免每个页面请求都命中会话存储。
你应该保持数据量相对较小,因为它将随着每个请求发送。
有了那个想法,继续前进…
如果数据不敏感,您可以使用由键/值对和共享密钥组合生成的 sha1哈希签署值。例如:
$values=array(
user_id =>1,
foo => bar
);
$secret= MySecretSalt ;
$plain="";
foreach($values as $key=>$value)
{
$plain.=$key. | .$value. | ;
}
$plain.=$secret;
$hash=sha1($plain);
现在给客户端一个包含所有值和哈希值的Cookie。当呈现Cookie时,您可以检查哈希值。如果您根据客户端呈现的值计算的哈希值与预期的哈希值不匹配,则知道这些值已被篡改。
对于敏感数据,你需要加密这些值。可以查看mcrypt扩展,该扩展提供了许多加密功能。
关于Cookie窃取,如果您在Cookie中放置用户凭据并信任它,则获取该Cookie的某人可以冒充该用户,直到密码更改为止。一个好习惯是记住您如何验证用户,只有在用户明确登录时才授予某些特权。例如,对于论坛,您可能允许某人发布帖子,但不允许更改其帐户详细信息,如电子邮件地址。
还有其他“自动登录”cookie的技巧,其中包括给这些cookie一个仅允许使用一次的令牌值。这里有一篇很好的文章介绍了这种技术。
您还可以考虑在已签名的cookie中包括客户端IP地址,如果它不匹配提交cookie的IP地址,则要求用户重新登录。这提供了更多的保护,但对于IP地址持续更改的人不起作用。您可以将其作为可选功能,并为用户提供退出的方式。这只是一个闲想,我没有在实践中看过这样的做法 :)
有关会话劫持、劫持和固定的详细说明,请参见Sessions and Cookies这篇不错的文章,其中提供了一些更多的技巧,例如使用User-Agent标头作为附加签名。
我为此目的专门制作了 CookieStorage。所有存储的值都是通过RIPEMD160哈希使用您的私钥进行安全签名(并通过时间进行加盐),并可选择使用RIJNDAEL256进行加密。
每个值都存储与时间戳,可检索。
Signed example.
Encrypted example.
如果您喜欢,您可以使用您选择的哈希/加密/解密函数。
在PHP中的Signed Cookies
对于这个问题的其他答案有点过时了。PHP 5.2 添加了“httponly”参数到“setcookie”函数中,有效地添加了本地签名cookie的支持。根据“setcookie”函数的“httponly”参数文档,链接为:http://php.net/manual/en/function.setcookie.php
当设置为"TRUE"时,cookie只能通过HTTP协议访问。这意味着cookie无法被脚本语言(如JavaScript)访问。有人建议这个设置可以有效地帮助减少XSS攻击的身份盗窃(虽然并非所有浏览器都支持此设置),但这种说法往往受到质疑。
将此参数设置为true也将禁用其他基于浏览器的工具(如Chrome的DevTools)对此Cookie进行编辑的能力。为了使签名的Cookie更加安全,我强烈建议缩小它所使用的路径或域。您可以使用path
和domain
参数来指定这些内容。当然,如果您的网站正在通过HTTPS加载,使用secure
参数来保护cookie也不会有坏处。结果将会是这样一行:
setcookie( signedCookie , uneditable value here , 0, / , www.example.com , TRUE , TRUE);
为什么使用签名的Cookie?
实际上,签名 cookie 在一些特定的情况下很有帮助,而其他的方法,比如会话,可能就不行了。比如,假设有一个网站或应用程序使用负载均衡器来提高性能,又假设该负载均衡器有多个物理服务器用于提供文件,并且没有启用粘性会话选项,这种情况下,签名 cookie 几乎是在 PHP 中保持状态的唯一安全方法。