首页 > 解决方案 > 使用 php MySQL 和 HTML 进行登录检查

问题描述

我正在为一项任务建立一个网站的登录页面。当我在检查用户详细信息的文件中散列密码时,它与数据库中存储的散列密码不匹配。代码总是转到最后一个 else 语句,并将我重新链接到错误密码 sv 等于 1 的登录页面。如果我没有对密码进行哈希处理,则将哈希密码从数据库复制并粘贴到登录表单中作品。如果有人可以提供帮助,将不胜感激

        ini_set('display_errors', 1);
        ini_set('log_errors',1);
        error_reporting(E_ALL);
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        session_start();

        $email = $_POST["email"];
        $pass1 = $_POST["pass"];
        $pass = hash('sha256', $pass1);

        if(isset($_SESSION['user_type']))
        {
            unset($_SESSION['user_type']);
        }

        include("group_detail.php");
        $query = "SELECT * from employee WHERE email = '$email' AND password = '$pass'";
        $result_employee = $db->query($query);
        $employee_row = mysqli_fetch_assoc($result_employee);

        if(!empty($employee_row)){

            $_SESSION['id'] = $employee_row['employee_ID'];
            $_SESSION['name'] = $employee_row['name'];
            $_SESSION['user_type'] = $employee_row['title'];
            header('Location: homepage.html');

        }else{

            $query = "SELECT * from customer WHERE email = '$email' AND password = '$pass'";
            $result_customer = $db->query($query);
            $customer_row = mysqli_fetch_assoc($result_customer);

            if(!empty($customer_row)){

                $_SESSION['id'] = $customer_row['customer_ID'];
                $_SESSION['name'] = $customer_row['name'];
                $_SESSION['user_type'] = 'Customer';
                $_SESSION['email'] = $customer_row['email'];
                header('Location: homepage.html');
            }

            else{

                $_SESSION['wrong_password'] = 1;
                header('Location: login.php');

            }
        }

注册码

<<?php
        // this code checks all reuired fields are filled in appropriately
        ini_set('display_errors', 1);
        ini_set('log_errors',1);
        error_reporting(E_ALL);
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        session_start();

        $nameErr = $phoneErr = $emailErr = $passwordErr = "";
        $name = $address = $eircode = $email = $password = $phone = "";
        $employee_ID = 0;

        function test_input($data) {
              $data = trim($data);
              $data = stripslashes($data);
              $data = htmlspecialchars($data);
              return $data;
            }

        if ($_SERVER["REQUEST_METHOD"] == "POST") {
          echo $nameErr;
          if (empty($_POST["name"])) {
            $nameErr = "Your name is required for registration";
          } else {
            $name = test_input($_POST["name"]);
            if (!preg_match("/^[a-zA-Z ]*$/",$name)) {
              $nameErr = "Only letters and a space allowed";
           }
          }

          if (empty($_POST["phone"])) {
            $phoneErr = "Your phone number is required for registration";
          } else {
            $phone = test_input($_POST["phone"]);
          }
          if(empty($_POST['email']))
          {
            $emailErr = "Your Email is required for registration";
          } else {
                include ("group_detail.php");
                $email_test = test_input($_POST["email"]);
                $sql = "SELECT * from customer WHERE email = '$email_test'";
                // Checks if another account uses this email
                            $result = $db->query($sql); // runs the query
                            $num_rows_3= mysqli_num_rows($result); // counts how many rows the query applies to
                if($num_rows_3 == 0){
                    // Sets email value if no one else has used this email to sign up before
                    $email = test_input($_POST["email"]);
                }
                else{
                    // Lets the customer know this email is already in use
                    $emailErr = "Another account has previously been registered with this email. If this is you, you can login ";
                }
          }
          if(empty($_POST['pass1']))
          {
            $passwordErr = "Password required";
          } else {
            $pass1 = $_POST['pass1'];
            $pass2 = $_POST['pass2'];
            if($pass1 == $pass2){
                $pass = hash('sha256',$pass1);
                // $pass = $pass1;
            } else{
                $passwordErr = "The passwords you enter must match";
            }
          }

          if(empty($_POST['address']))
          {
            $address = "";
          }else{
            $address = test_input($_POST['address']);
          }

          if(empty($_POST['eircode']))
          {
            $eircode = "";
          }else{
            $eircode = test_input($_POST['eircode']);
          }



          if ($phoneErr == "" && $nameErr == "" && $passwordErr == "" && $emailErr == "")
          {
            // This code enters the data from the form into the customer table
            include ("group_detail.php");

            $q  = "INSERT INTO customer(";
            $q .= "name, phone, password, email, address, eircode";
            $q .= ") VALUES (";
            $q .= "'$name', '$phone', '$pass', '$email', '$address', '$eircode')";

            $result = $db->query($q);

            $sql = "SELECT customer_ID FROM customer ORDER BY customer_ID DESC LIMIT 1";
            $result1 = $db->query($sql);
            $row = mysqli_fetch_assoc($result1);
            $_SESSION['customer'] = $row['customer_ID'];
            header('Location: homepage.html');
          }
        }

    ?>

标签: phphtmlmysqlauthenticationhash

解决方案


解决方案

您的字段长度不正确。当您使用SHA256哈希函数时,您会得到类似于以下内容的输出:

ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f    // password123

如果您只有密码字段,15 characters则保存的值将被截断:

ef92b778bafe771

但是,在比较过程中,登录脚本的完整值用于与存储在 DB 中的截断版本进行比较,因此不存在匹配项。因为,正如您在上面看到的,它们并不相同。

要修复您需要对ALTER表格进行修复,以便该字段至少为varchar(64). 然后新帐户将按预期工作(注意:旧哈希仍然无法工作 - 他们需要重做!


附加信息

您的代码还有其他一些问题...

  1. 您不应该将变量直接放入您的代码中。相反,最好使用带有参数化查询的Prepared Statementbind ,稍后您将在其中使用变量。
    • 这基本上意味着在查询中我们使用一个占位符?,我们需要一个变量,然后bind稍后将变量分配给占位符
    • 这主要是为了防止SQL注入,保护你输入不正确
  2. 最好使用 PHP 内置函数password_*hash密码verify
    • 它比简单地使用更安全hash
    • salts是自动生成的,可以保护您免受彩虹表之类的影响
    • 的默认算法需要字符password_hash的字段长度60+
  3. 无需在 SESSION 中存储多余的数据
    • 数据已存储在数据库中,因此只需在需要时获取它
  4. 似乎你有一张桌子customers和另一张桌子employees
    • 这不是一个好的设计,应该有一个表users,然后您可以为employeecustomer等设置标志supplier
  5. 您的test_input函数执行通常在显示而不是保存时完成的功能。

下面是一个快速重写,解决了上面的一些问题(注意:下面的代码不完整,例如,它没有执行所有相同的验证 - 例如检查非法字符 - 这只是为了说明目的

登记

<?php

ini_set('display_errors', true);
ini_set('log_errors', true);
error_reporting(E_ALL);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

session_start();

$errors = [];

$name    = $_POST["name"]    ?? null;
$phone   = $_POST["phone"]   ?? null;
$email   = $_POST['email']   ?? null;
$address = $_POST['address'] ?? null;
$eircode = $_POST['eircode'] ?? null;
$pass1   = $_POST['pass1']   ?? null;
$pass2   = $_POST['pass2']   ?? null;


// Check passwords are the same and assign hash to $pass
$pass = $pass1 === $pass2 ? password_hash($pass1, PASSWORD_DEFAULT) : null;


// Check the required fields are present and not empty
if (!$name || !$phone || !$email || !$pass) {
    $errors[] = "Required fields are missing.";
}


// Check if the email address already exists in the DB
$checkEmailExistsSQL   = "SELECT COUNT(*) as countEmails FROM user WHERE email = ?";
$checkEmailExistsQuery = $mysqli->prepare($checkEmailExistsSQL);
$checkEmailExistsQuery->bind_param("s", $email);
$checkEmailExistsQuery->execute();

$emailExists = $checkEmailExistsQuery->get_result()->fetch_assoc()["countEmails"];

if ($emailExists !== 0) {
    $errors[] = "The email address already exists in the DB";
}


// Check if there were errors and output them; then exit the script
if (count($errors)) {
    foreach($errors as $error) {
        echo $error, PHP_EOL;
    }
    exit;
}

include("group_detail.php");

$insertSQL = "
    INSERT INTO user
        (name, phone, password, email, address, eircode)
    VALUES
        (?, ?, ?, ?, ?, ?)
";

$insertQuery = $mysqli->prepare($insertSQL);
$insertQuery->bind_param("ssssss", $name, $phone, $pass, $email, $address, $eircode);
$insertQuery->execute();

// Success the user is registered

登录

<?php

ini_set('display_errors', true);
ini_set('log_errors', true);
error_reporting(E_ALL);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

session_start();

$email = $_POST["email"] ?? null;
$pass  = $_POST["pass"]  ?? null;

// You can remove the old user id. But you don't need to
// 
// There's no need to store excess data on the user in
// the SESSION super global; any data that you need
// access to can be retrieved from the DB at will.
// Copying data into SESSION only eats into memory.
unset($_SESSION["id"]);

// Check that something was submitted for email and password
if (!$email || !$pass) {
    echo "Error: all fields need to be completed";
    exit;
}

include("group_detail.php");

$sql   = "SELECT id, password FROM user WHERE email = ?";
$query = $mysqli->prepare($sql);
$query->bind_param("s", $email);
$query->execute();

// Check to see if the email address is registered.
// Then check to see if the password is a match.
if (
    !($user = $query->get_result()->fetch_assoc())
    || !password_verify($pass, $user["password"])
) {
    echo "Error: the email address or password isn't correct";
    exit;
}


// Success the user is logged on
// 

$_SESSION["id"] = $user["id"];

推荐阅读