我已经写了很多关于安全登录和“记住我”复选框的文章。公认的答案没有错,但我认为它在某个方面比它需要的要复杂一些,并且忽略了需要更多复杂性的领域。
在服务器端生成并存储一个 nonce,用用户名和其他信息(例如客户端 ip、计算机名、时间戳、类似的东西)对其进行哈希处理,并将其发送到 cookie 中。随机数应与到期日期一起存储在数据库中,并在 cookie 返回时进行检查。
因此,不向客户端公开任何信息的实现可能看起来像......
// Storage:
setcookie(
'rememberme',
hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce),
time() + 8640000 // 100 days, for example
);
// Validation:
$valid = hash_equals(
$_COOKIE['rememberme'],
hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce)
);
这里明显的限制是,如果您的 IP 地址(或其他信息)发生变化,您的 cookie 将毫无用处。有些人可能认为这是一件好事,我认为它对 Tor 用户的可用性产生了不必要的敌意。
您当然可以将上述引用解释为不同的意思,例如穷人的 JSON Web 令牌。但是,每个域的 HTTP cookie 限制为 4 KiB。空间非常宝贵。
另一个问题:你的数据库查询泄露了多少关于你的应用程序的信息?(是的,我说的是旁道。)
Paragon Initiative 的安全“记住我”策略
贮存:
random_bytes()
从(PHP 7.0+ 或通过random_compat )生成一个随机的 9 字节字符串,base64 将其编码为 12。这将用于数据库查找。
- 生成另一个随机字符串,最好至少 18 个字节长,并再次对其进行 base64 编码(到 24+)。这实际上将用于身份验证。
- 存储
$lookup
并hash('sha256, $validator)
入库;当然与特定的用户帐户相关联。
- 存储
$lookup . $validator
在用户的 HTTP cookie 中(例如rememberme
)。
验证(自动登录):
- 将 cookie 拆分为
$lookup
和$validator
。
- 基于
$lookup
;执行数据库查找 如果这里有定时侧信道也没关系。
- 检查
hash_equals($row['hashedValdator'], hash('sha256', $validator))
。
- 如果第 3 步返回
TRUE
,请将当前会话与适当的用户帐户相关联。
安全分析:
此策略在Gatekeeper中实现。