【问题标题】:Query SQL for username and return password [duplicate]查询用户名并返回密码的 SQL [重复]
【发布时间】:2011-10-26 20:16:17
【问题描述】:

我有一个用户名和密码数据库。我需要创建一个“忘记密码”函数并让它在表中搜索用户名并返回该用户的密码。然后我希望它发送一封电子邮件,说明姓名和密码。

这是我为特定用户查询数据库的工作代码:

<?php
session_start();

include "config.php";

if($_POST['nameQuery']) {

$query = "SELECT * FROM myDatabase WHERE name = '" .$_POST['nameQuery']. "'";  
$result = mysql_query($query);  
if (mysql_num_rows($result) > 0) { 
    //User exists
    echo '1'; 
} else { 
    mysql_query($query);
//User does not exist
echo '0'; 
}
}
?>

【问题讨论】:

  • 很好,你有什么问题?
  • 提防Bobby Tables
  • @Chase:我看到您在上一个问题 (stackoverflow.com/questions/7054553/query-two-sql-entries) 中获得了有关 SQL 注入的建议。请注意。您可以在这里看到人们对此有强烈的感觉,这是有充分理由的。
  • +1 以获得更高的可见性,希望您能够获得更充实的响应,从而在安全方面为您提供帮助。

标签: php sql passwords


【解决方案1】:

请勿在您的数据库中存储密码。永远不应该存储明文密码。您应该存储密码的哈希值,以帮助防止它们在其他网站上使用。请参阅Best way to store password in database 了解更多信息。

【讨论】:

  • 我希望我能更多地支持这个。不要存储真实密码。不要存储未加盐的哈希。如果用户忘记了密码,请向他们发送一个新密码。或者更好的是,如果您可以改用 OpenID 之类的东西。
  • hash('SHA256', $str) 应该是最小的哈希值。
  • hash('SHA256', $str.$salt) :-)
【解决方案2】:

您的代码不安全!您的$_POST['nameQuery'] 是通往SQL Injection 的华丽大门

最低限度的安全措施是对所有输入进行转义和清理

$nameQuery = mysql_real_escape_string ($_POST['nameQuery']);

黄金法则:永远不要相信传入的数据

【讨论】:

  • 这是最低要求,参数化查询更简洁,同时更安全,
【解决方案3】:

社区维基:

不要。因为这意味着您将保存可检索的密码。最好将密码更改链接发送到他们的电子邮件,以便访问一次性密码重置页面。这样,在有权访问该用户电子邮件的人完成重置周期之前,密码不会更改。

通过这种方式,您可以适当地散列密码并仅根据散列检查传入的密码。

此外,我建议您查看 php 的 PDO,因为您当前正在创建对 sql-injection 有效的 sql 查询。

【讨论】:

    【解决方案4】:

    我有几个建议给你

    1. 不要向那里的人发送密码,而是向他们提供更改密码的链接
    2. 看看 kjetilh 的建议

    祝你好运,编码愉快

    【讨论】:

    • 并参考 Ned Batchelder 的建议
    【解决方案5】:

    第一件事是第一件事:您可能希望确保不会通过登录获得SQL-injected,因为您实际上是在将用户输入注入到您的查询中......大不。

    交换这个:

    $query = "SELECT * FROM myDatabase WHERE name = '" .$_POST['nameQuery']. "'";  
    

    ...为此:

    $query = sprintf(
        'SELECT * FROM myDatabase WHERE name = \'%s\'', 
        mysql_real_escape_string($_POST['nameQuery'])
    );
    

    接下来是您所要求的:一种获取用户用户名和密码的方法。虽然我不建议您实际以明文形式存储密码以供所有人查看,但您必须自己做出决定。

    这个 sn-p 会做的事:

    <?php
        //Get the data from the DB
        $query = sprintf(
            'SELECT * FROM myDatabase WHERE name = \'%s\'', 
            mysql_real_escape_string($_POST['nameQuery'])
        );
        $result = mysql_query($query);
        $user_info = mysql_fetch_assoc($result);
    
        //Check if it's valid
        if( isset($user_info['name']) ) {
    
            //Construct the message
            $message = 'Your username is: ' . $user_info['name'] . "\n"
            $message .= 'Your password is: ' . $user_info['password'] . "\n";
    
            //Send it to the appropriate email
            $status = mail(
                $user_info['email'], 
                'Password recovery for ' . $user_info['name'], 
                $message
            );
    
            //Check if it actually worked
            if( $status ) echo 'Mail sent. Check your inbox. Login again. Thank you.';
            else echo 'The password recovery couldn\'nt be sent. Please try again later.';
    
        } else { 
    
            echo 'No user found with the supplied username.', 
                'Please try again (with another username)';
    
        }
    ?>
    

    Edit: Adding password recovery-functionality

    对于您在下面请求的密码恢复功能,您可以尝试以下操作:

    recover_password.php:

    <?php
        session_start();
    
    
        //mysql_connect()-here
    
        //Initalize the variable
        $do_update_password = false;
    
        //Grab the  token
        $token = isset($_REQUEST['token'])? $_REQUEST['token'] : '';
        $is_post_request = isset($_POST['update_pwd'])? true : false;
        $is_recovery_request = isset($_POST['request_recovery'])? true : false;
        $message = '';
    
        //Check if we're supposed to act upon a token
        if( $is_recovery_request ) {
    
            //Grab the email
            $email = isset($_POST['email'])? $_POST['email'] : '';
    
            //Create the query, execute it and fetch the results
            $sql = sprintf(
                'SELECT `user_id` FROM myDatabase WHERE `email` = \'%s\'',
                mysql_real_escape_string($email)
            );
            $result = mysql_query($sql);
            $user_info = mysql_fetch_assoc($result);
    
            //Validate the response
            if( isset($user_info['user_id') ) {
    
                //Let's generate a token
                $date = date('Y-m-d H:i:s');
                $token = md5($email . $date);
    
                //Create the "request"
                $sql = sprintf(
                    'INSERT INTO myRequests (`user_id`, `token`, `date`) VALUES (\'%s\', \'%s\', \'%s\')',
                    $user_info['user_id'],
                    mysql_real_escape_string($token),
                    $date
                );
                $result = mysql_query($sql);
    
                //Validate
                if( mysql_affected_rows($result) == 1 ) {
    
    
                    //Construct the message
                    $message = 'Your username is: ' . $user_info['email'] . "\n"
                    $message .= 'Please click on the following link to update your password: http://yoursite.com/request_password.php?token=' . $token . "\n";
    
                    //Send it to the appropriate email
                    $status = mail(
                        $email, 
                        'Password recovery for ' . $email, 
                        $message
                    );
    
                    //Check if it actually worked
                    if( $status ) {
    
                        echo 'Mail sent. Check your inbox. Login again. Thank you.';
    
                    } else {
    
                        echo 'The password recovery couldn\'nt be sent. Please try again later.';
    
                    }
    
                } else {
    
                    $message = 'The DB-query failed. Sorry!';
    
                }
    
            } else {
    
                $message = 'The specified e-mail address could not be found in the system.';
    
            }
    
        } elseif( $token != '' ) {
    
            //Check so that the token is valid length-wise (32 characters ala md5)
            if( !isset($token[31]) || !isset($token[32])  ) { 
    
                $message = 'Invalid token!';
    
            } else {
    
                //Construct the query and execute it
                $sql = sprintf(
                    'SELECT `user_id` FROM myRequest WHERE `token` = \'%s\'', 
                    mysql_real_escape_string($token);
                );
                $result = mysql_query($sql);
    
                //Fetch the rows
                $request_info = mysql_fetch_assoc($result);
    
                //Check for a valid result
                if( isset($request_info['user_id']) ) {
    
                    $message = 'Update your password below.';
                    $do_update_password = true;
    
                } else {
    
                    $message = 'No record found for the following token: ' . $token);
    
                }
            }
        } elseif( $is_post_request ) {
    
            //Grab the new password
            $password = isset($_POST['password'])? $_POST['password'] : '';
    
            //Construct the query
            $sql = sprintf(
                'UPDATE myDatabase SET `password` = \'%s\' WHERE `user_id` = ( SELECT `user_id` FROM myRequest WHERE `token` = \'%s\' )', 
                mysql_real_escape_string($password),
                mysql_real_escape_string($token)
            );    
    
            //Execute it, and check the results
            $result = mysql_query($sql);
            if( $result !== false ) {
    
                //Did we succeed?
                if( mysql_affected_rows($result) === 1 ) {
    
                    //Remove the old recovery-request
                    $sql = sprintf(
                        'DELETE FROM myRequests WHERE `token` = \'%s\'',
                        mysql_real_escape_string($token)
                    );
                    $result = mysql_query($sql);
    
                    //^We don't actually need to validate it, but you can if you want to
                    $message = 'Password updated. Go have fun!';
    
                } else {
    
                    $message = 'Could not update the password. Are you sure that the token is correct?';
    
                }
    
            } else {
    
                $message = 'Error in the SQL-query. Please try again.';
    
            }
        }
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <title>Password recovery</title>
            <style>
                form > * { display: block; }
            </style>
        </head>
        <body>
            <h1><?php echo $message; ?></h1>
            <?php if( $do_update_password ): ?>
    
                <form method="post">
                    <label for="token">Token:</label>
                    <input type="text" name="token" id="token" value="<?php echo $token; ?>" />
                    <label for="password1">Password:</label>
                    <input type="text" name="password[]" id="password1" />
                    <label for="password2">Password (again):</label>
                    <input type="text" name="password[]" id="password2" /> 
                    <input type="submit" name="update_pwd" value="Update your password!" />
                </form>
    
            <?php elseif($is_post_request && $token != ''): ?>
    
                <h2>Request that might've updated your password. Exciting!</h2>
    
            <?php else: ?>
    
                <form method="post">
                    <label for="email">E-mail address:</label>
                    <input type="text" name="email" id="email" />
                    <input type="submit" name="request_recovery" value="Request a new password" />
                </form>
    
            <?php endif; ?>
        </body>
    </html>
    

    请注意,我没有时间实际测试代码,但我认为只要稍加调整就可以正常工作。哦,在我忘记之前,您需要将下表添加到数据库中:

    myRequests的表结构

    CREATE TABLE IF NOT EXISTS `myRequests` (
      `request_id` int(6) NOT NULL AUTO_INCREMENT,
      `token` varchar(32) NOT NULL,
      `user_id` int(6) NOT NULL,
      `date` datetime NOT NULL,
      PRIMARY KEY (`request_id`),
      UNIQUE KEY `token` (`token`,`user_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
    

    祝你好运!

    【讨论】:

    • 得到了这个工作,但因为我以 MD5 格式存储密码,我无法将它们转换回原始密码。我想我需要一种新的方法来做到这一点,例如提供一个指向一次性页面的链接来更改密码。在不泄露可能被攻击者修改的链接的情况下,我将如何做到这一点?
    • 我用一个(希望能正常工作的)完整解决方案更新了我的帖子,希望它对你有用。 :-)
    【解决方案6】:

    虽然与您的原始问题相切,但我想指出,以纯文本形式存储密码是一个坏主意。您应该在数据库中存储密码的散列版本。然后,您可以散列用户输入并将其与数据库中用于登录的内容进行比较。

    相反,您忘记的密码应该创建一个新的(临时)密码,并将其哈希值存储在数据库中,同时将纯文本密码发送到存档的电子邮件帐户。

    【讨论】:

      【解决方案7】:

      只需阅读结果:

      /* ... */
      if (mysql_num_rows($result) > 0) {
        // User exists
        $row = mysql_fetch_row($result);
        print_r($row);
      }
      /* ... */
      

      更一般的说明:您的代码中存在 SQL 注入漏洞,请查看该主题,否则攻击者将能够读取您所有用户的密码。

      此外,不建议将密码以明文形式存储在数据库中。请使用 sha1 或 sha256 之类的哈希算法来存储密码。

      【讨论】:

        【解决方案8】:

        我会建议你把你的桌子设计改成

        • 用户名
        • 密码'存储哈希
        • 密码检索问题'存储哈希
        • 密码检索答案'存储哈希

        登录时根据散列密码检查用户,类似这样

        $_POST['password']=sha1($_POST['password']);
        

        登录时使用 sql like
        select col1,col2,.. from tbl where user=?和密码=?然后用 $_POST['username'], $_POST['password']

        填充参数

        所以使用 Prepared Statement 或 PDO

        当用户忘记密码时使用相同的逻辑

        【讨论】:

          【解决方案9】:
          <?php
          session_start();
          
          include "config.php";
          
          if($_POST['nameQuery']) {
          
              $query = "SELECT * FROM myDatabase WHERE name = '" .mysql_real_escape_string($_POST['nameQuery']). "'";  
              $result = mysql_query($query) or die ('Error: '.mysql_error());  
              if (mysql_num_rows($result) > 0) { 
                  $row = mysql_fetch_assoc($result);
                  $message = 'Your password is: '.$row['password'];
                  if(mail($row['user_email'], 'Lost password', $message)){
                      echo 'Password sent';
                  }
              } else { 
                  echo 'Nu such user'; 
              }
          }
          ?>
          

          【讨论】:

            【解决方案10】:

            您必须从 mysql_query 结果(存储在$result 变量中)中检索用户名和密码,如下所示:

            $row = mysql_fetch_array($result);
            $username = $row['username'];
            $password = $row['password'];
            

            然后使用php的mail()函数发送邮件。

            【讨论】:

            • 除了他明显的代码缺陷之外,我确实回答了他如何实现他想做的事情。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-19
            • 1970-01-01
            • 2014-04-18
            • 1970-01-01
            相关资源
            最近更新 更多