【问题标题】:Forgotten password scenario - how to create a token忘记密码场景 - 如何创建令牌
【发布时间】:2011-10-12 11:40:08
【问题描述】:

我想在 Web 应用程序中实现忘记密码的场景。系统将向用户发送一封电子邮件,其中包含一个唯一的 URL,用户可以点击该 URL 以允许他们重置密码。网上有很多关于这方面的指导。以下是一个很好的链接,建议如何实现这一点。 Best way of doing code for "Forgotten Password"

我不完全理解的部分是令牌生成。这是什么意思??这只是存储在服务器上针对用户(可能在用户数据库表中)的 guid(或随机字符串)。 guid 也在 url 中发送(作为查询字符串),因此当请求到达 web 服务器时,它可以查找 guid 并找到要重置的用户帐户。还有比这更多的吗?许多人谈论令牌到期。我可以根据 guid 存储过期时间,之后无法完成帐户重置。

有些人建议使用 CSRF 令牌,但我不明白这在这种情况下是如何工作的。

任何指导将不胜感激... :)

【问题讨论】:

    标签: security token


    【解决方案1】:

    在服务器端存储(至少)128 位随机生成的令牌,连同用户名和到期日期,将非常有效。

    实现相同目的的另一种方法(无需在服务器端存储任何内容)是计算

    hash = hash(secret + user name + expiration date)
    

    其中+ 表示连接,hash() 是加密安全哈希函数(如SHA2),secret 是(至少)128 位的字符串,只有 您 em>,并将其发送给用户:

    user name + expiration date + hash
    

    两种方法都实现了相同的安全性,但请注意 - 在令牌过期之前 - 用户可以多次更改他的密码。

    在第一种情况下,确保 token 是随机创建的(例如,如果您使用的是 linux,则使用 /dev/random)。第二个中的secret 也是如此。但是secret 是静态的(不是为每个请求新生成的)。

    【讨论】:

    • 后者将使令牌对多次使用有效。
    • @Gumbo:没错。但只要到期日期足够短,我就不会认为这是一个问题。由于(可悲)电子邮件几乎总是使用不安全的连接发送、传递和/或阅读,因此到期日期不应超过几分钟。这就是为什么,就个人而言,我宁愿依靠其他密码恢复选项,也不愿通过电子邮件发送令牌......
    • 我宁愿使用两者的组合:将随机生成的令牌与用户 ID 和到期日期一起存储在服务器端。这也使得跟踪已发行的代币成为可能。
    • @Gumbo:当然,您必须将令牌绑定到用户。如果没有,用户A 请求一个令牌并使用它来更改用户B 的密码。我虽然这是含蓄的,但我会更改我的答案以使其明确。
    • 好的,所以当我们谈论令牌时,我们只是在谈论一系列字节(首选 128 位,即 guid)。我猜一个 guid 对 url 不是很友好,所以使用其他东西可能更好??
    【解决方案2】:

    我使用这段代码来生成我的令牌:

    /**
     * generates a random token, uses base64: 0-9a-zA-Z/+
     * @param int [optional] $length length of token, default 24 (144 Bit)
     * @return string token
     */
    function generateToken($length = 24) {
            if(function_exists('openssl_random_pseudo_bytes')) {
                $token = base64_encode(openssl_random_pseudo_bytes($length, $strong));
                if($strong == TRUE)
                    return substr($token, 0, $length); //base64 is about 33% longer, so we need to truncate the result
            }
    
            //fallback to mt_rand if php < 5.3 or no openssl available
            $characters = '0123456789';
            $characters .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+'; 
            $charactersLength = strlen($characters)-1;
            $token = '';
    
            //select some random characters
            for ($i = 0; $i < $length; $i++) {
                $token .= $characters[mt_rand(0, $charactersLength)];
            }        
    
            return $token;
    }
    

    来源:http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php#96812

    【讨论】:

      猜你喜欢
      • 2017-01-11
      • 2019-07-13
      • 2014-06-19
      • 2020-01-28
      • 2017-02-25
      • 1970-01-01
      • 2014-06-27
      • 2019-12-03
      相关资源
      最近更新 更多