【问题标题】:Change and Confirm Password MySql PHP更改和确认密码 MySql PHP
【发布时间】:2019-01-28 13:13:45
【问题描述】:

所以我有一个用户可以更改密码的页面,但我希望它更安全,通过询问用户旧密码然后是新密码,我只是不知道如何验证任何人都可以提供帮助请问我?
这是我的实际代码:

    <?php
//Inicio de uma session que autentica e valida o login feito em login.php
  session_start(); 
  //Redirecionar um Admin ou um SuperAdmin para a devida página com as devidas permissões! 
include '../functions/redirect.php';
 isAuthenticated();
 $user = $_SESSION['users']['username'];

?>
<!DOCTYPE html>
<?php

    require '../functions/database.php';

    if ( !empty($_POST)) {
        // Manter a validação dos erros
        $usernameError = null;
        $passwordError = null;

        $password = $_POST['password'];
        // $confirm_password = null;
        // $new_password = null;

        // Validar os inputs
        $valid = true;

          if (empty($password)) {
            $passwordError = 'Introduza a password!';
            $valid = false;
        }

        // Inserir os dados
     if ($valid) {
            $pdo = Database::connect();
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $password = password_hash($password, PASSWORD_BCRYPT);
            $sql = "UPDATE users SET password = ? WHERE username = '$user'";
            $q = $pdo->prepare($sql); 
            $q->execute(array($password)); 
            header("Location: index.php");
            Database::disconnect();
    }

 }

?>

【问题讨论】:

  • 你到底卡在哪里了?如果您想在更新前检查旧密码,只需通过用户名获取用户并验证密码即可?就像登录一样。
  • 您的代码有两个问题。 1. 你没有在任何地方设置$user 变量。 2. 您正在为密码使用参数化准备语句(这很好),但您也应该真的将它用于用户名。用户名可能更危险,因为它没有经过哈希处理。
  • @MagnusEriksson 在页面顶部我定义了$user $user = $_SESSION['users']['username'];
  • 您应该向我们展示 all 相关代码(这样我们就知道所有变量包含什么,并且您不会错过定义任何变量或出现拼写错误)。不管怎样,如果你看过我之前的两篇cmets,你应该可以做一些尝试。
  • 我已经更新了我的问题

标签: php mysql passwords


【解决方案1】:

我假设您的表单中有一个“old_password”和一个“new_password”字段供用户填写。您首先检查输入的旧密码与您的用户表中已有的散列密码。

注意使用过滤器在将表单中输入的信息传递给 SQL 查询之前对其进行过滤。

如果一切正常,您可以继续测试您输入的新密码。 如果新密码得到验证,那么您继续更新您的用户表。

// Connect to database
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$valid = false;
if ( !empty($_POST)) {
    // Manter a validação dos erros
    $usernameError = null;
    $passwordError = null;

    // Read in old password from form field
    $old_password = filter_var($_POST['old_password'], FILTER_SANITIZE_STRING);

    // Validar os inputs
    if (empty($old_password)) {
        $passwordError = 'Introduza a password!';
        $valid = false;
    }

    // Check old password
    else {
        // Read in old password from db            
        // build SELECT statement with variable
        $sql = 'SELECT password FROM users WHERE username = :USER';
        $sql->bindValue(':USER', $user);
        $sql->execute();

        if ($sql->rowCount() > 0) {
            // Read in value from select
            $row = $sql->fetchObject();
            $user_password = $row->password;

            // Test entered password against hashed current user password
            if (password_verify($old_password, $user_password)) {
                $valid = true;
            }

            else {
                // passwords do not match
                $valid = false
            }
        }
        else {
            // Did not find user in table
            $valid = false;
        }
    }
}

// Inserir os dados
 if ($valid) {
    // Test new password
    $new_password = filter_var($_POST['new_password'], FILTER_SANITIZE_STRING);

    // here you would test length, or content or whatever ...

    // if still valid you save the new password
    $new_password = password_hash($new_password, PASSWORD_BCRYPT);
    $sql = "UPDATE users SET password = :NEWPASSWORD WHERE username = :USER';
    $sql->bindValue(':NEWPASSWORD', $new_password);
    $sql->bindValue(':USER', $user);
    $sql->execute();

    // header("Location: index.php");
}

Database::disconnect();

【讨论】:

  • 在散列之前不必escape passwords 或对它们使用任何其他清理机制。这样做会更改密码并导致不必要的额外编码。
  • 虽然我同意@JayBlanchard 的观点,即转义密码可能会产生不必要的额外编码,但它绝对不会更改密码,因为我在许多网站和 PHP 脚本中都使用过它。但是,我认为,我同意在发送到 SQL 查询之前对密码进行哈希处理是不必要的。
  • 感谢您的 awnser,实际上我的数据库中只有一个密码字段
  • @Carlos 在我的答案/示例中,数据库中只有一个密码字段。但是,您的表单中应该至少有 2 个密码字段(1/old 和 2/new),我同意 Chris 的观点,您实际上应该在表单上有 3 个密码字段(1/old、2/new 和 3/confirm new ) 强制用户在将新密码发送到数据库之前正确输入两次新密码。
  • @DerekErb - “它绝对不会更改密码” ...当然会。转义/清理字符串的唯一目的是更改它们。取字符串:&lt;hello&gt;&lt;/hello&gt;。清理将更改它的字符串:``(空字符串)。因此,应该使用转义或净化字符串。想象一下有人有密码:&lt;foo&gt;password&lt;/foo&gt;。如果您对其进行清理,它将变为password,我们都同意这将是您可能拥有的最糟糕的密码之一。您有效地使用户密码方式更加不安全。
【解决方案2】:

我还要指出,$_POST 提交后的 $valid = true 没有任何意义,因为您通过发送一个 $_POST 来使 $valid 为真,无论输入是什么,只要有东西在那里并且为密码更新您实际上需要所有数据。 然后稍后检查附加要求,然后将 $valid 更改为 false。

您应该从 $valid = false 开始,当满足要求时,您可以将其返回为 True。

此外,为了补充 Derek 的回答,我建议您进行额外的小检查,以确保用户必须检查新密码两次,以避免他们犯错并因此无法登录的情况。

【讨论】:

    【解决方案3】:

    为此,您必须处理 2 次:

    第一次你必须得到用户的当前密码。验证他的身份:

    $password = $_POST['password'];
    if (password_verify($password, $remote->password))
       // the password is right
    

    ->remote是sql请求的结果

    然后,第二次,您将比较新密码和此密码的确认。如果它们相同:

    $new = $_POST['new_password'];
    $confirm = $_POST['confirm'];
    if ($new == $confirm)
       $new = password_hash($new, PASSWORD_BCRYPT);
       // execute your sql insertion
    

    请原谅我的英语

    【讨论】:

      猜你喜欢
      • 2018-03-19
      • 1970-01-01
      • 2012-02-12
      • 2016-08-14
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      • 1970-01-01
      • 2021-02-24
      相关资源
      最近更新 更多