php - 使用 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');
}
}
?>
解决方案
解决方案
您的字段长度不正确。当您使用SHA256
哈希函数时,您会得到类似于以下内容的输出:
ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f // password123
如果您只有密码字段,15 characters
则保存的值将被截断:
ef92b778bafe771
但是,在比较过程中,登录脚本的完整值用于与存储在 DB 中的截断版本进行比较,因此不存在匹配项。因为,正如您在上面看到的,它们并不相同。
要修复您需要对ALTER
表格进行修复,以便该字段至少为varchar(64)
. 然后新帐户将按预期工作(注意:旧哈希仍然无法工作 - 他们需要重做!)
附加信息
您的代码还有其他一些问题...
- 您不应该将变量直接放入您的代码中。相反,最好使用带有参数化查询的Prepared Statement
bind
,稍后您将在其中使用变量。- 这基本上意味着在查询中我们使用一个占位符
?
,我们需要一个变量,然后bind
稍后将变量分配给占位符 - 这主要是为了防止SQL注入,保护你输入不正确
- 这基本上意味着在查询中我们使用一个占位符
- 最好使用 PHP 内置函数
password_*
和hash
密码verify
。- 它比简单地使用更安全
hash
salts
是自动生成的,可以保护您免受彩虹表之类的影响- 的默认算法需要字符
password_hash
的字段长度60+
- 它比简单地使用更安全
- 无需在 SESSION 中存储多余的数据
- 数据已存储在数据库中,因此只需在需要时获取它
- 似乎你有一张桌子
customers
和另一张桌子employees
- 这不是一个好的设计,应该有一个表
users
,然后您可以为employee
、customer
等设置标志supplier
。
- 这不是一个好的设计,应该有一个表
- 您的
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"];
推荐阅读
- angular - 表单组对象绑定和验证的角度反应表单模块数组
- json - Jinja 通过 Ansible URI 模块模板化 Json GraphQL 查询
- android - Alt Beacon Library、RegionBootstrap 和 BeaconManager 同时工作
- macos - 无法在 MAC(Mojave)上运行 Qt 安装程序应用程序
- python - 如何防止错误消息显示在屏幕上
- angular - 角度步进器,一步显示多个组件
- python - 是否可以使用命名变量对 Pyspark 数据框进行通配符过滤?
- ajax - 对 RestControler Spring 的 Ajax 请求返回 403 错误
- reporting-services - 如何为系列组获取折线图的百分比值?/如何通过 sql 表绘制图形?
- asp.net-core - 在 MVC 控制器中提交按钮操作