php - 忘记密码电子邮件重置 php 工作,除了原始密码和更改密码都不允许登录

标签 php mysql authentication passwords

我为我的登录系统创建了一个忘记密码更改 php 函数,它向忘记密码的用户发送一封电子邮件,并提供一个使用散列 token 的链接以更改他们的密码。一旦用户选择了电子邮件链接,他们就可以更改密码,然后用新的散列密码更新 mysql。

在我尝试使用新密码登录之前,代码的各个方面似乎都能正常工作。我收到回显“用户名/密码组合不正确”(在 LOGIN.PHP 页面上找到)。尝试原始密码也会在 LOGIN.PHP 页面上回显相同的错误。

不确定为什么我的 sql 查询没有将更新后的密码与现有用户名匹配并允许登录?

为了便于通过代码进行解析,我排除了我认为不是问题的部分。我包含了 5 个 php 文件。

忘记密码.PHP

<?php
if (!isset($_GET['email'])) {
    echo '<form action="">//Form for password reset here</form>';
    exit();
}


define('DB_USER', '');
define('DB_PASS', '');
define('DB_NAME', '');

$email = $_GET['email'];

function connect()
{
//Connect to db
}
connect();

$q = "SELECT email FROM users WHERE LCASE(TRIM(email))='" . strtolower(trim($email)) . "'";
$r = mysql_query($q);
$n = mysql_num_rows($r);

if ($n == 0) {
    echo "Email id is not registered";
    die();

}

//token updated into sql db for user
    $token=getRandomString(10);
    $q="UPDATE users SET token=('".$token."') WHERE email=('".$email."')";
    mysql_query($q);

function getRandomString($length) 
   {

//token created
}
//email creation code here

重置.PHP

<?php
session_start();

//Define db connection parameters

    $token=$_GET['token'];

function connect() {

//Connection to db executed
    }

connect();

if(!isset($_POST['password'])){
    $q="SELECT email FROM users WHERE token='".$token."' and used='0'";
    $r=mysql_query($q);
    while($row=mysql_fetch_array($r))
   {

$email=$row['email'];
   }

If ($email!=''){
      $_SESSION['email']=$email;
}

    else die("Invalid link or Password already changed");}

$password=$_POST['password'];
$email=$_SESSION['email'];

if(!isset($password)){

echo '
//Change password form
';}

if(isset($_POST['password'])&&isset($_SESSION['email']))
{

//Update sql db with newly created password
$q="UPDATE users SET password='".md5($password)."' WHERE email='".$email."'";
$r=mysql_query($q);

if($r)mysql_query("UPDATE users SET used='1' WHERE token='".$token."'");echo "Your password is changed successfully";
if(!$r)echo "An error occurred";
}
?>

LOGIN.PHP(显示错误消息)

<div id="loginContainer">
<div id="loginMessage">
        <?php if ( $logged == 'invalid' ) : ?>
            <p class="name_pass">
                The username/password combination is incorrect. Try again.
            </p>
        <?php endif; ?>
        <?php if ( $_GET['reg'] == 'true' ) : ?>
            <p class="success">Your registration was successful, please login below.
            </p>
        <?php endif; ?>
        <?php if ( $_GET['action'] == 'logout' ) : ?>
            <?php if ( $loggedout == true ) : ?>
                <p class="log_out">You have been successfully logged out.
                </p>
            <?php else: ?>
                <p class="problem">There was a problem logging you out.
                </p>
            <?php endif; ?>
        <?php endif; ?>
        <?php if ( $_GET['msg'] == 'login' ) : ?>
            <p class="must_login">You must login to view this content. Please login below.
                </p>
        <?php endif; ?>
</div>

CLASS.PHP(登录函数)

        function login($redirect) {
        global $jdb;

        if ( !empty ( $_POST ) ) {


            $values = $jdb->clean($_POST);


            $subname = $values['username'];
            $subpass = $values['password'];


            $table = 'users';


            $sql = "SELECT * FROM $table WHERE username = '" . $subname . "'";
            $results = $jdb->select($sql);


            if (!$results) {
                die('Sorry, that username does not exist!');
            }


            $results = mysql_fetch_assoc( $results );


            $storeg = $results['date'];


            $stopass = $results['password'];


            $nonce = md5('registration-' . $subname . $storeg . NONCE_SALT);


            $subpass = $jdb->hash_password($subpass, $nonce);


            if ( $subpass == $stopass ) {


                $authnonce = md5('cookie-' . $subname . $storeg . AUTH_SALT);
                $authID = $jdb->hash_password($subpass, $authnonce);


                setcookie('logauth[user]', $subname, 0, '', '', '', true);
                setcookie('logauth[authID]', $authID, 0, '', '', '', true);


                $url = "http" . ((!empty($_SERVER['HTTPS'])) ? "s" : "") . "://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
                $redirect = str_replace('login.php', $redirect, $url);


                header("Location: $redirect");
                exit;   
            } else {
                return 'invalid';
            }
        } else {
            return 'empty';
        }
    }

INDEX.PHP(登录成功后的登陆页面)

<?php
require_once('load.php');
$logged = $j->checkLogin();

if ( $logged == false ) {
    //Build our redirect
    $url = "http" . ((!empty($_SERVER['HTTPS'])) ? "s" : "") . "://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
    $redirect = str_replace('index.php', 'login.php', $url);

    //Redirect to the home page
    header("Location: $redirect?msg=login");
    exit;
} else {
    //Grab our authorization cookie array
    $cookie = $_COOKIE['logauth'];

    //Set our user and authID variables
    $user = $cookie['user'];
    $authID = $cookie['authID'];

    //Query the database for the selected user
    $table = 'users';
    $sql = "SELECT * FROM $table WHERE username = '" . $user . "'";
    $results = $jdb->select($sql);

    //Kill the script if the submitted username doesn't exit
    if (!$results) {
        die('Sorry, that username does not exist!');
    }

    //Fetch our results into an associative array
    $results = mysql_fetch_assoc( $results );
?>

感谢您提供的所有帮助。我感谢任何愿意看一下代码来帮助我弄清楚登录过程的最后一部分的人。 谢谢。

最佳答案

在您的 reset.php 文件中,您存储了密码的未加盐 MD5...

$password=$_POST['password'];
$q="UPDATE users SET password='".md5($password)."' WHERE email='".$email."'";

...但随后您将它与不同的东西进行比较...

$subpass = $values['password']; // seems to be the entered password
...
$stopass = $results['password']; // seems to be the stored MD5 password hash
...
$subpass = $jdb->hash_password($subpass, $nonce); // probably not an unsalted MD5
if ( $subpass == $stopass ) // comparison of different things

即使您让这段代码工作,这也是一个非常不安全的解决方案。相反,您绝对应该切换到 PHP 中内置的密码哈希函数。 DB 字段应为 varchar(255),代码可能如下所示:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($_POST['password'], PASSWORD_DEFAULT);
$q="UPDATE users SET password='".$hashToStoreInDb."' WHERE email='".$email."'";

要检查密码,您需要从数据库中获取哈希并将其与 password_verify 进行比较,因此比较将使用与存储哈希相同的盐来完成。

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $stopass.
$subpass = $values['password'];
...
$stopass = $results['password'];
...
$isPasswordCorrect = password_verify($subpass, $stopass);
if ($isPasswordCorrect)

您代码中的另一个问题是 SQL 注入(inject),您可以通过使用准备好的语句来避免此漏洞。您可以在另一个 answer 中找到 MySqli 或 PDO 的示例.

关于php - 忘记密码电子邮件重置 php 工作,除了原始密码和更改密码都不允许登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43566558/

相关文章:

php - Kohana 框架 - Ajax 实现最佳实践

mysql - 带连接的sql更新

linux - 没有密码的ssh两台计算机同一网络

具有多个选择的 Mysql group by 子句

authentication - 如何在 Jenkins 中使用 Github 个人访问 token

java - 放心测试-API请求401错误请求

php - 如何渲染ajax返回的文件

php - 在 PHP 中的 50K 行 CSV 文件中查找最长匹配项的最快方法

php - 从 javascript 到 PHP 的值

php - 我怎样才能结合 2 个复杂的 mysql 查询