birke / rememberme
安全的“记住我”功能
Requires
- php: ^7.4 || ^8.0
Requires (Dev)
- escapestudios/symfony2-coding-standard: ~3.11
- ircmaxell/random-lib: ^1.1
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.5
Suggests
- ext-pdo: *
- ircmaxell/random-lib: For generating random tokens with different entropy sources
- predis/predis: Needed if you used Redis storage
This package is auto-updated.
Last update: 2024-08-29 03:26:07 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.php
和user_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
的自定义类中实现您的令牌生成,并将该类作为构造函数参数传入。
在登录发生时,旧版本中不太安全的伪随机令牌将被更安全的令牌替换。为了更好的安全性(但可能减少用户的便利性),在更新后您可以在一次清除您的令牌存储。