【问题标题】:Generating confirmation code for an email confirmation为电子邮件确认生成确认代码
【发布时间】:2011-01-06 12:49:10
【问题描述】:

使用 PHP,有哪些方法可以生成随机确认码,可以存储在数据库中并用于电子邮件确认?我一生都想不出一种方法来生成可以从用户个人资料中生成的唯一编号。这样我就可以使用一个函数来使数字足够小以包含在 URL (see this link) 中。请记住,用户必须单击链接以“确认/激活”他/她的帐户。如果我不能使用数字,我可以同时使用字母和数字。

话虽如此,我已经尝试将用户名与“盐”一起散列以生成随机代码。我知道必须有更好的方法,所以让我们听听。

【问题讨论】:

    标签: php email-validation


    【解决方案1】:
    $random_hash = md5(uniqid(rand(), true));
    

    这将是 32 个字母数字字符长且唯一。如果你想让它更短,只需使用 substr():

    $random_hash = substr(md5(uniqid(rand(), true)), 16, 16); // 16 characters long
    

    生成随机数据的替代方法包括:

    $random_hash = md5(openssl_random_pseudo_bytes(32));
    $random_hash = md5(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
    
    // New in PHP7
    $random_hash = bin2hex(random_bytes(32));
    

    【讨论】:

    • +1 不错,独一无二,不基于用户数据。也就是说,我认为 uniqid 的最右侧部分比左侧更独特,因此您可能希望使用 -16, 16 作为 substr。
    • 在不可避免的问题出现之前:您必须对大约 18,000,000,000,000,000,000 个项目进行哈希处理,然后才有 50% 的可能性获得两个相同的哈希值。这是 5.84 亿年来每毫秒一个哈希值。所以是的,它们将是独一无二的。
    • 好的,谢谢大家!这与查询哈希码和用户名应该足够好,不是吗?
    • openssl_random_pseudo_bytes 函数的随机性比 rand() 好太多了。
    • @middaparka:好主意!但由于 substr 应用于哈希 (md5),而不是 uniqid,因此在这种情况下不会产生影响。
    【解决方案2】:

    1) 在数据库中创建一个激活字段

    2) 注册后发送电子邮件

    3) 创建要包含在电子邮件中的链接,使用唯一标识符 它看起来像这样

    欢迎用户名感谢您的注册。

    请点击下面的链接激活您的帐户

    domain.com/register.php?uid=100&activate=1
    

    4) 将激活字段更新为 true


    (来源:jackborn.com

    $email_encrypt = urlencode($email);
    $special_string = 'maybeyourcompanynamereversed?';
    $hash = md5($email_encrypt.$special_string);
    
    Here is the link that is sent to the email that was provided:
    
    http://yourdoman.com/confirm.php?hash='.$hash.'
    
    The actual link will look something like this:
    
    http://yourdomain.com/confirm.php?hash=00413297cc003c03d0f1ffe1cc8445f8
    

    【讨论】:

    • +1 图片和代码。使用数据库有助于跟踪代码......并处理过期等。
    • 但出于安全原因需要删除激活记录
    • 很好的逐步解释,但请注意,如果 $special_string(或您的源代码)的值是公开的,任何人都可以注册任何电子邮件地址并创建相应的哈希。或者换句话说:可以激活任何电子邮件地址而不拥有它。
    • -1 这是不完整且不可能的:如何在后端激活帐户,无法从哈希中恢复电子邮件
    【解决方案3】:

    接受的答案建议使用 PHP 的 uniqid() 的哈希值。 documentation for uniqid 明确警告它不会创建“随机或不可预测的字符串”,并强调“此函数不得用于安全目的。

    如果您担心确认码被猜到的可能性(这就是发布代码的全部意义),您可能希望使用更随机的生成器,例如openssl_random_pseudo_bytes()。然后,您可以使用bin2hex() 将其变成漂亮的字母数字。以下看起来就像 John Conde 的答案的输出,但(据说)更加随机且不易猜测:

    // generate a 16 byte random hex string
    $random_hash = bin2hex(openssl_random_pseudo_bytes(16))
    

    后期附录:正如 Oleg Abrazhaev 指出的那样,如果您想确保您的系统实际上能够在运行时生成加密强的随机值,openssl_random_pseudo_bytes 接受对 bool 的引用以报告这。来自phpinspectionsea docs的代码:

    $random = openssl_random_pseudo_bytes(32, $isSourceStrong);
    if (false === $isSourceStrong || false === $random) {
        throw new \RuntimeException('IV generation failed');
    }
    

    然后像之前一样使用生成的随机值:

    $random_hash = bin2hex($random)
    

    【讨论】:

      【解决方案4】:

      决定我需要一些更强大和附加功能的东西。所以这就是我想出的。

      /**
       * Hash Gen 
       * @author Kyle Coots
       * @version    1.0
       * Allow you to create a unique hash with a maximum value of 32.
       * Hash Gen uses phps substr, md5, uniqid, and rand to generate a unique 
       * id or hash and allow you to have some added functionality.
       * 
       * @see subtr()
       * @see md5()
       * @see uniqid()
       * @see rand()
       *  
       * You can also supply a hash to be prefixed or appened
       * to the hash. hash[optional] is by default appened to the hash 
       * unless the param prefix[optional] is set to prefix[true].     
       * 
       * @param start[optional]
       * @param end[optional]
       * @param hash[optional]
       * @param prefix bool[optional]
       * 
       * @return string a unique string max[32] character
       */
      function hash_gen($start = null, $end = 0, $hash = FALSE, $prefix = FALSE){
      
          // start IS set NO hash
          if( isset($start, $end) && ($hash == FALSE) ){
      
              $md_hash = substr(md5(uniqid(rand(), true)), $start, $end);
              $new_hash = $md_hash;
      
          }else //start IS set WITH hash NOT prefixing
          if( isset($start, $end) && ($hash != FALSE) && ($prefix == FALSE) ){
      
              $md_hash = substr(md5(uniqid(rand(), true)), $start, $end);
              $new_hash = $md_hash.$hash;
      
          }else //start NOT set WITH hash NOT prefixing 
          if( !isset($start, $end) && ($hash != FALSE) && ($prefix == FALSE) ){
      
              $md_hash = md5(uniqid(rand(), true));
              $new_hash = $md_hash.$hash;
      
          }else //start IS set WITH hash IS prefixing 
          if( isset($start, $end) && ($hash != FALSE) && ($prefix == TRUE) ){
      
              $md_hash = substr(md5(uniqid(rand(), true)), $start, $end);
              $new_hash = $hash.$md_hash;
      
          }else //start NOT set WITH hash IS prefixing
          if( !isset($start, $end) && ($hash != FALSE) && ($prefix == TRUE) ){
      
              $md_hash = md5(uniqid(rand(), true));
              $new_hash = $hash.$md_hash;
      
          }else{
      
              $new_hash = md5(uniqid(rand(), true));
      
          }
      
          return $new_hash;
      
       } 
      

      【讨论】:

        【解决方案5】:
          private  function generateCodeSecurity()
          {
            list($usec, $sec) = explode(" ", microtime());
            $micro = usec + $sec;
        
            $hoy = date("Y-m-d");  
            $str = str_replace('-','',$hoy); 
        
            return  rand($str,  $micro);
        
          }
        

        使用这个小代码,您可以生成一个随机数,范围为 7 到 11 个数字。

        使用php函数:

        Rand ();
        Microtime ()
        
        
        
        $hoy = date("Y-m-d");  
        $str = str_replace('-','',$hoy); 
        
        echo $str; 
        result date: 20170217
        
        
        
         list($usec, $sec) = explode(" ", microtime());
         $micro = usec + $sec;
        
        
        echo $micro;
        result  micro varaible: 1487340849
        

        在这个函数中传递参数:rand ();

         rand($str,  $micro);
        

        然后返回;

        示例:

         list($usec, $sec) = explode(" ", microtime());
            $micro = usec + $sec;
        
            $hoy = date("Y-m-d");  
            $str = str_replace('-','',$hoy); 
        
           $finalresult = rand($str,  $micro);
        
        echo $finalresult; 
        

        结果: 1297793555

        我认为这个数字很难重复,因为它永远不会是同一天,也不是同一小时,也不是相同的毫秒时间。

        【讨论】:

        • 虽然欢迎使用此代码 sn-p,并且可能会提供一些帮助,但它会是 greatly improved if it included an explanation of howwhy 这解决了问题。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。特别是,您应该解释这是非常容易猜测的,并且不适合预期目的。
        猜你喜欢
        • 2011-01-12
        • 2021-08-05
        • 1970-01-01
        • 2017-05-23
        • 2014-11-03
        • 2017-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多