birke/rememberme

安全的“记住我”功能

4.0.1 2021-04-26 19:20 UTC

README

此库实现了在网站上实现安全“记住我”功能的最佳实践。登录信息和唯一的加密令牌存储在Cookie中。如果用户访问网站,则将Cookie中的登录信息与服务器上存储的信息进行比较。如果令牌匹配,则用户登录。用户可以在多个计算机/浏览器上拥有登录Cookie。

此库深受Barry Jaspan的文章《改进的持久登录Cookie最佳实践》的启发。该库可以防止以下攻击场景

  • 用户的计算机被偷或被破坏,使攻击者能够使用现有的“记住我”Cookie登录。用户知道发生了这件事。用户可以远程使所有登录Cookie失效。
  • 攻击者获取了“记住我”Cookie并使用它登录。用户不知道这件事。下次他尝试使用被偷的Cookie登录时,他会收到警告,并且所有登录Cookie都会失效。
  • 攻击者从服务器获取了登录令牌的数据库。存储的令牌是经过散列的,因此他需要付出计算上的努力(彩虹表或暴力破解)才能使用它们。
  • 攻击者试图通过系统性地生成“记住我”Cookie进行暴力破解登录。默认安全设置下,每秒100次尝试(这是一个非常高的数字,可能会出现在服务器日志中),猜测Cookie值正确的几率在8个月后为50%。

安装

composer require birke/rememberme

使用示例

请参阅example目录中的示例。您可以使用以下命令在本地计算机上运行它:

php -S 127.0.0.1:8085 -t example

要了解基本应用程序结构,请查看index.phpuser_is_looged_in.php模板。

示例使用文件系统在服务器端存储令牌。在大多数情况下,最好将存储与PDOStorage类交换。

Cookie配置

默认情况下,Cookie的有效期为一周,并且适用于设置它的域中的所有路径。它无法通过JavaScript访问/更改,并且将在HTTP连接上传输。如果您的应用程序需要不同的配置(例如,如果您正在使用HTTPS并希望通过仅允许通过安全连接传输Cookie来增强安全性),您可以创建自己的PHPCookie实例

$expire = strtotime("1 week", 0);
$cookie = new PHPCookie("REMEMBERME", $expire, "/", "", true, true);
$auth = new Authenticator($storage, null, $cookie);

令牌安全

此库默认使用random_bytes函数生成16字节的令牌(32字符的十六进制字符串)。这应该对大多数应用程序足够安全。

如果您需要更高的安全性,请使用自定义令牌生成器实例化Authenticator类。以下示例生成128字符的Base64编码令牌:

$tokenGenerator = new DefaultToken(94, DefaultToken::FORMAT_BASE64);
$auth = new Authenticator($storage, $tokenGenerator);

如果您对生成随机令牌的控制欲更强,请参阅RandomLib。Rememberme有一个RandomLibToken类可以用来使用它。

清理过期令牌

从您的存储(文件系统或数据库)中清理过期令牌的最佳方法是编写一个小脚本,该脚本初始化您的令牌存储类并调用其cleanExpiredTokens方法。定期使用cron作业或其他工作方法运行此脚本。

如果您不能定期运行清理脚本并且网站流量较低,您可以在每次页面调用时通过如下初始化Authenticator类来清理存储:

 $auth = new Authenticator($storage);
 $auth->setCleanExpiredTokensOnLogin(true);

从版本1.x更新

首先,您需要更新Authenticator::login方法的检查结果。它不再返回布尔值/凭据,而是返回一个结果对象,必须查询该对象以确定成功、失败和凭据。请参阅示例了解具体操作方法。

如果您已经使用自定义的createToken方法扩展了Authenticator类,您需要在实现TokenInterface的自定义类中实现您的令牌生成,并将该类作为构造函数参数传入。

在登录发生时,旧版本中不太安全的伪随机令牌将被更安全的令牌替换。为了更好的安全性(但可能减少用户的便利性),在更新后您可以在一次清除您的令牌存储。