我正在使用PHP,我知道在这个网站上存在许多类似的问题。但我没有找到关于以下几点的精辟解释:
目前,我认为我只有以下选项来设计一个好的激活器链接:
在用户表中存储唯一令牌和两个参数以验证帐户激活:用户标识符和数据库上的相应令牌。可能是这样的:
$user->token = bin2hex(openssl_random_pseudo_bytes(16));
hostname/accountConfirm?user=username&token=userUniqueToken
仅使用一个参数作为具有散列秘密值+用户电子邮件字符串的令牌。此选项不需要任何数据库列来存储令牌。像这样:
$secret = 'some_secret_string';
$hashedToken = password_hash( $secret . $user->email, PASSWORD_DEFAULT );
hostname/accountConfirm?token=($hashedToken)
我的问题:
这些的利弊是什么?
如果有,还有什么其他好的解决方案?
答案 0 :(得分:1)
访问数据库比访问数据库更危险,尤其是未经身份验证的用户。通过使用基于散列的消息身份验证代码(HMAC),可以避免在此步骤中访问数据库。这也会减慢脚本小子试图填满你的数据库的速度。
所以,我喜欢你的第二个选项,但你仍然需要在某个地方保留电子邮件地址/用户名。
这就是我所使用的(伪代码):
$email = 'user@example.com';
$expires = current time + 24 hours;
$userIP = getUserIP();
$hmac = hmac_function( $serverSecret, $email + $expires + $userIP );
//correctly escaping query params of course...
$confirmationURL = https://hostname/accountConfirm?email=$email&expires=$expires&ip=$userIP&hmac=$hmac
将网址发送至$ email
$email = $_GET['email'];
$expires = $_GET['expires'];
$userIP = $_GET['ip'];
$hmac = $_GET['hmac'];
$expectedHmac = hmac_function( $serverSecret, $email + $expires + $userIP);
if($expectedHmac != $hmac) {
log 'evil request';
throw 400 error;
}
//check user ip
//check expiry time
//proceed with registration
如果某人对IP,电子邮件或到期时间感到困惑,则HMAC将无法匹配。