【问题标题】:Username correct, password incorrect?用户名正确,密码错误?
【发布时间】:2010-12-25 15:57:12
【问题描述】:

在登录系统中,如何判断用户是否输入了错误的密码?您是否执行两个 SQL 查询,一个查找用户名,然后一个查找用户名和匹配的(加盐+散列等)密码?我问这个是因为如果用户输入的密码不正确,我想更新我的 failed_login_attempts 列。

如果您执行两个查询,这不会增加开销吗?

如果您进行这样的查询,您将如何判断输入的密码是否正确,或者用户名是否不存在:

 SELECT * FROM author 
 WHERE username = '$username'
 AND password = '$password'
 LIMIT 1

( ^ NB:我保持简单,将使用哈希和盐,并将在真实的输入中清理输入。)

类似这样的:

$user = perform_Query() // get username and password?

 if ($user['username'] == $username && $user['password'] == $password)
 {
     return $user;
 }
 elseif($user['username'] == $username && $user['password'] !== $password)
 {   // here the password doesn't match
     // update failed_login_attemps += 1
 }

【问题讨论】:

    标签: php sql login


    【解决方案1】:

    你想多了。只需要一个查询:

    SELECT * FROM author WHERE username = '$username';
    

    然后做:

    if ($user['password'] == saltedHash($password,$user['salt'])) {
        return "successful";
    }
    else {
        return "failed";
    }
    

    用户名必须是唯一的。否则这是行不通的。我建议不要让用户名不唯一,因为除此之外它还会引起很多其他问题。

    【讨论】:

    • SELECT username,password FROM ... +1 虽然
    • @Robert: 或SELECT username,password,salt ...。这提醒了我,我的示例代码中有一个错误......已修复。
    【解决方案2】:

    如果执行两个查询不会增加开销吗?

    我会说这并不重要。许多复杂的 Web 框架在每个请求中发出数十或数百个查询。或多或少不会改变太多。

    我认为这真的取决于偏好。在我看来,获取整个用户行,然后在 PHP 端检查密码是最有意义的,因为您已经有了更新 failed_logins 列所需的 ID。

    【讨论】:

    • 我要补充一点,单次更新的成本是 10 次额外选择的 1000 倍
    • +1,因为我个人认为人们对运行多个查询有点过分了。
    • @Robert 是的。我见过 每个请求 有 600-700 个查询的插件载货 Drupal 站点。相比之下,或多或少看起来真的不重要!
    • 是的,在那里建立自己的网站的人会运行 10~20 个查询,并且每个请求还要担心 1 个:/
    【解决方案3】:

    我们所做的是执行一个查询来查找用户(基于 userid),然后我们选择 UserId、PwSalt 和 PwHash。

    如果没有找到用户,那么我们知道这是一个无效的用户名。

    如果找到用户,我们对密码进行哈希处理,并将其与查询中的 pwHash 进行比较。如果哈希值不匹配,我们会更新失败的登录尝试。

    【讨论】:

      【解决方案4】:

      在您的代码中,如果用户名或密码不正确,$user 将为空

      SELECT password = '$password' AS is_legit, * 
      FROM author 
      WHERE username = '$username'
      LIMIT 1
      
      $user = perform_Query() // get username and password?
      // $user will be empty if the username is incorrect
      $user_exists = $user.length > 0;
      // to make sure we don't address a 
      // non-existent array element
      if($user_exists && $user['password'] == $password){ 
           return $user;
      }
      elseif($user_exists && $user['password'] !== $password)
      {   // here the password doesn't match, but the user does
          // update failed_login_attemps += 1
          // be sure to let the user know that the penetration
          // attempt is halfway complete
      }
      else{
          // F4il
      }
      

      【讨论】:

        【解决方案5】:

        和许多其他人)创建登录系统的方式是这样的:

        • 注册时
          • 创建一个唯一的哈希并与用户名、密码一起存储
        • 登录时
          • 从数据库中提取用户名、密码、哈希
          • 使用子句WHERE username = '$username'
          • 如果有 1 行,则用户名正确
          • 使用hash($post_pass,$user_hash) 构建一个已编译的哈希并与$user_pass 进行比较

        此外,如果您在方法的 1 点返回任何内容,那么之后的任何内容都不会运行,所以

        if ($user['username'] == $username && $user['password'] == $password)
         {
             return $user;
         }
         elseif($user['username'] == $username && $user['password'] !== $password)
         {   // here the password doesn't match
             // update failed_login_attemps += 1
         }
        

        可以修改为

        if ($user['username'] == $username && $user['password'] == $password)
        {
            return $user;
        }
        return false
        

        因为如果满足($user['username'] == $username && $user['password'] == $password),那么return会在那里执行,因为false不会被执行。

        希望这会有所帮助。

        【讨论】:

        • @Col,在什么情况下,通常存储哈希意味着每个人的哈希都是唯一的。减少密码破解者发生冲突的机会。
        • 你在说什么碰撞?我没听错吗,你确实将这个哈希 与密码一起存储了吗?
        • 有一个用户名、密码(加密)、用原始密码加盐的哈希。和碰撞,例如 md5 碰撞。 mscs.dal.ca/~selinger/md5collision
        • 是的,您说得对,我们将密码存储在数据库中,仍然存在安全风险,但比使用永不更改的站点范围的哈希值更安全。 elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql
        • 您似乎被一些“明智的建议”塞满了,但一点也不懂。然后你机械地重复它,与实际问题和常识没有任何关系
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-08
        • 2018-11-20
        • 1970-01-01
        • 2015-06-08
        • 2020-07-19
        • 1970-01-01
        • 2017-01-06
        相关资源
        最近更新 更多