【问题标题】:Storing passwords and usernames in a database; going from PHP hashed to SQL and back在数据库中存储密码和用户名;从 PHP 散列到 SQL 并返回
【发布时间】:2013-01-01 20:23:43
【问题描述】:

我正在尝试扩展我对 SQL 和 PHP 的了解,因此我正在尝试弄清楚如何在我正在处理的项目中为用户凭据创建散列数据库条目。现在在计划阶段,我将所有内容存储到会话 cookie 中,但在最终产品中,我希望将所有内容存储在我的服务器上。我有一些关于加盐/散列字符串的文档,但我不确定如何存储然后检查存储的散列是否正确。

<?php
    $username = $_GET["$us"];
    $password = $_GET["$pa"];
    $expire = time()+60*60*24*14; //Cookies expire in two weeks
    setcookie("username", $username, $expire);
    setcookie("password", $password, $expire);
?>

现在我有一个登录页面,使用上面的代码将 $us 和 $pa 发布到 login-submit.php 页面。如果我使用 md5 或类似方法对其进行哈希处理,我将如何将其存储在我的数据库中,当从登录页面拉出时,检查密码是否正确?我在想:

<?php
    $userhash = md5($us);
    $passhash = md5($pa);
    $rows = $db->query("
        INSERT INTO credentials
        VALUES ($passhash, $userhash);"
    );
?>

这样好吗?顺便说一句,我将如何检查数据库中是否存在用户,如果存在,将 md5 哈希反转回纯文本以便我可以使用它?

【问题讨论】:

  • 按照设计,您无法反转散列(尽管 Internet 上可以使用查找表来反转琐碎的密码,因此您还应该使用盐渍,正如 Andrew 所说)。要在登录时检查密码,请对输入执行相同的散列,并将结果与​​数据库中的散列密码进行比较。

标签: php sql


【解决方案1】:
  1. 不要使用 cookie。使用sessions。 (会话自动将内容存储在服务器上,只需使用 cookie 来检索它)。

  2. 其次,MD5 对密码不安全。它有碰撞,很容易受到暴力攻击。请参阅此问题的第一个答案:How can I store my users' passwords safely?

【讨论】:

    【解决方案2】:

    不使用cookies,而是使用sessions,它们将数据存储在服务器端。对于密码加密,请使用使用 crypt() 的非常安全的河豚算法。

    【讨论】:

      【解决方案3】:

      这可能是我发现的最好的密码散列脚本。所有好的用户站点都应该首先从登录脚本开始,而不是稍后。

      Hashing a password

      我用它创建了一个类来准备数据库插入的密码,效果很好。

      这是课程:

          <?php
      /**
      * User Login Class
      *
      * LICENSE:      (http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2)
      *
      * COPYRIGHT:    Finley Designs
      * CONTACT:      ffrinfo@yahoo.com
      * DESIGNED BY:  Roy Finley
      * VERSION:  1.0
      * Password hashing with PBKDF2.
      * This class uses the pdkdf2 functions designed by : havoc AT defuse.ca : www: https://defuse.ca/php-pbkdf2.htm
      * 
      */
      class PasswordProcessor
      {
      //CREATE HASH FROM USER PASSWORD FOR NEW USER OR LOST PASSWORD
      public function create_hash($password)
      {
          // format: algorithm:iterations:salt:hash
          $salt = base64_encode(mcrypt_create_iv(24, MCRYPT_DEV_URANDOM));
          return  "sha256:1000:" .  $salt . ":" . 
              base64_encode($this->pbkdf2(
                  "sha256",
                  $password,
                  $salt,
                  1000,
                  24,
                  true
              ));
      }
      //VALIDATE USER PASSWORD
      public function validate_password($password, $good_hash)
      {
          $params = explode(":", $good_hash);
          if(count($params) < 4)
             return false; 
          $pbkdf2 = base64_decode($params[3]);
          return $this->slow_equals(
              $pbkdf2,
              $this->pbkdf2(
                  $params[0],
                  $password,
                  $params[2],
                  (int)$params[1],
                  strlen($pbkdf2),
                  true
              )
          );
      }
      
      // COMPARE TWO STRINGS IN LENGTH-CONSTANT TIME.
      private function slow_equals($a, $b)
      {
          $diff = strlen($a) ^ strlen($b);
          for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
          {
              $diff |= ord($a[$i]) ^ ord($b[$i]);
          }
          return $diff === 0; 
      }
      //HASHING ALGORITHM
      private function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
      {
          $algorithm = strtolower($algorithm);
          if(!in_array($algorithm, hash_algos(), true))
              die('PBKDF2 ERROR: Invalid hash algorithm.');
          if($count <= 0 || $key_length <= 0)
              die('PBKDF2 ERROR: Invalid parameters.');
      
          $hash_length = strlen(hash($algorithm, "", true));
          $block_count = ceil($key_length / $hash_length);
      
          $output = "";
          for($i = 1; $i <= $block_count; $i++) {
              // $i encoded as 4 bytes, big endian.
              $last = $salt . pack("N", $i);
              // first iteration
              $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
              // perform the other $count - 1 iterations
              for ($j = 1; $j < $count; $j++) {
                  $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
              }
              $output .= $xorsum;
          }
      
          if($raw_output)
              return substr($output, 0, $key_length);
          else
              return bin2hex(substr($output, 0, $key_length));
      }
      }//CLOSE PasswordProcessor CLASS
      ?>
      

      请记住,这只是验证用户身份的一小部分.....搜索谷歌并阅读,阅读,阅读 其他要点

      • 您的数据库需要两个用户 - 一个只能读取用于登录和 一个可以读写注册脚本的。

      • 在注册表单上使用验证码

      • 永远不要告诉用户登录的哪一部分失败了,只是它确实失败了。

      【讨论】:

        【解决方案4】:

        将输入的(密码+盐)的哈希与存储的(密码+盐)的哈希进行比较。您还需要将盐存储在数据库中。

        编辑:无需对用户名进行哈希处理。您将无法从哈希中提取它。但是,您可以对其进行加密。

        【讨论】:

          猜你喜欢
          • 2012-07-22
          • 2019-03-14
          • 2012-07-06
          • 2011-03-30
          • 2011-08-28
          • 2011-08-23
          • 1970-01-01
          • 2011-12-15
          • 2012-02-10
          相关资源
          最近更新 更多