激活链接:哪种设计最佳方式?

时间:2015-08-19 04:19:24

标签: php security

我正在使用PHP,我知道在这个网站上存在许多类似的问题。但我没有找到关于以下几点的精辟解释:

  • 激活器的约定链接
  • 激活器链接上的常见漏洞

目前,我认为我只有以下选项来设计一个好的激活器链接:

  1. 在用户表中存储唯一令牌和两个参数以验证帐户激活:用户标识符和数据库上的相应令牌。可能是这样的:

    $user->token = bin2hex(openssl_random_pseudo_bytes(16));

    hostname/accountConfirm?user=username&token=userUniqueToken

  2. 仅使用一个参数作为具有散列秘密值+用户电子邮件字符串的令牌。此选项不需要任何数据库列来存储令牌。像这样:

    $secret = 'some_secret_string';

    $hashedToken = password_hash( $secret . $user->email, PASSWORD_DEFAULT );

    hostname/accountConfirm?token=($hashedToken)

  3. 我的问题:

    • 这些的利弊是什么?

    • 如果有,还有什么其他好的解决方案?

1 个答案:

答案 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

在accountConfirm处理程序中:

$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将无法匹配。