密码无法在我的 login.php 中验证
Password is failing to validate inside my login.php
当我注册时,它对密码进行哈希处理,然后将用户名和哈希后的密码放入我的本地数据库中。工作正常。当我尝试登录时,用户名和密码与本地数据库中的任何一个都不匹配,它向我抛出名为 login=error2 的错误消息到 url,如果出现问题,我已经为这种情况编写了该消息那部分代码。所以你应该在 login.php 中寻找 error2。我认为问题就在那里。我整天都卡在上面,无法正常工作。
p.s。我是一名前端开发人员,我使用的最复杂的框架是 jquery 和 React,所以如果我对 php/mysql 听起来很愚蠢,我很抱歉。我在 3 天前开始学习 php。
我在 80 端口使用 XAMPP 本地主机,
这是我使用的 phpmyadmin sql 代码(数据库名称是 pixl_users)
创建tableuser_info(
用户名 varchar(12) 不为空,
密码 varchar(30),
电子邮件 varchar(30),
性别整数(1),
日期日期时间不为空
);
$(document).ready(function () {
//switch to login form
$('#switch-to-login').click(function () {
$('#form-register').hide();
$('#form-login').show();
});
//switch to registration form
$('#switch-to-signup').click(function () {
$('#form-login').hide();
$('#form-register').show();
});
});
========================================
signup.php file
<?php
if (isset($_POST['register'])) {
include_once 'db-connect.php';
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
if ((empty($username) || empty($password)) || $username == "admin" || $username == "Admin") {
// if fields are empty, send back to index and say error msg
header("Location: index.php?fields=empty");
exit();
} else {
// check for characters which are not allowed in the registration fields
if (!preg_match('/^[a-zA-Z0-9_.\s]+$/i', $username) || !preg_match('/^[a-zA-Z0-9_.!\s]+$/i', $password)) {
header("Location: index.php?fields=invalidcharacters");
exit();
} else {
//check if username is longer than 2 and shorter than 13 characters
if (strlen($username) > 2 && strlen($username) < 13) {
// check if username is taken
$sql = "SELECT * FROM user_info WHERE username='$username'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0) {
header("Location: index.php?fields=userTaken");
exit();
} else {
//hashing the password
$hashedPass = password_hash($password, PASSWORD_DEFAULT);
//insert the user into the database
$insert = "INSERT INTO user_info (username, password)
VALUES ('$username', '$hashedPass')";
//query it into the database
mysqli_query($conn, $insert);
//send user to the main website page
header("Location: index.php");
}
} else {
echo "Username can't be shorter than 3 characters and longer than 12 characters!";
}
}
}
}
login.php file
<?php
session_start();
if (isset($_POST['login'])) {
// connect to local database
include 'db-connect.php';
// get username and password from inputs
$username = mysqli_real_escape_string($conn, $_POST['login-username']);
$password = mysqli_real_escape_string($conn, $_POST['login-password']);
//check if fields are empty
if (empty($username) || empty($password)) {
header("Location: index.php?fields=empty");
exit();
} else {
// put usernames from table into array $resultCheck
$sql = "SELECT * FROM user_info WHERE username='$username'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
// if there is 0 usernames in database throw error
if ($resultCheck < 1) {
header("Location: index.php?login=error1");
exit();
} else {
if ($row = mysqli_fetch_assoc($result)) {
//De-hashing the password
$hashedPassCheck = password_verify($password, $row['password']);
if ($hashedPassCheck == false) {
header("Location: index.php?login=error2");
exit();
} elseif ($hashedPassCheck == true) {
// log in the user
$_SESSION['user_name'] = $row['username'];
header("Location: index.php?login=success");
exit();
}
}
}
}
} else {
header("Location: index.php?login=error");
exit();
}
<?php session_start(); ?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>database test</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<style>
body {
background-color: black;
color: white;
}
#form-register {
display: none;
}
</style>
</head>
<body>
<button id="switch-to-login">switch to login</button>
<button id="switch-to-signup">switch to signup</button>
<!-- register -->
<form id="form-register" action="signup.php" method="POST">
<input id="inp-username" type="text" name="username" placeholder="choose a name" /><br />
<input id="inp-password" type="password" name="password" placeholder="choose a password" />
<button id="btn-register" name="register" type="submit">Register</button>
</form>
<!-- login -->
<form id="form-login" action="login.php" method="POST">
<input id="inp-username" type="text" name="login-username" placeholder="login name" /><br />
<input id="inp-password" type="password" name="login-password" placeholder="password" />
<button id="btn-login" name="login" type="submit">Login</button>
</form>
<script src="script.js"></script>
</body>
</html>
如果您多次调用 $hash = password_hash($newRegistrantPassword, PASSWORD_DEFAULT)
,即使您输入的密码相同,您每次都会得到不同的 $hash
。那是因为该函数每次都会生成不同的随机散列。 (如果您对原因感到好奇,请查看 彩虹表 。)
如果您将 $hash
存储在没有足够字符的数据库列中,您将截断它。那很糟。 通过使用 VARCHAR(255)
作为散列密码来验证您的应用程序的未来。
面向未来是什么意思? php 开发人员认识到计算机变得更快,网络小鬼变得更聪明,密码更容易破解。所以他们添加了 password_needs_rehash()
function 。在 php 的未来版本中,他们可能会更改 PASSWORD_DEFAULT
哈希方法,使哈希更难破解。
对于期望寿命长的应用程序来说,好的密码验证码可能看起来像这样。
$valid = password_verify ( $passwordPresentedByUser, $storedHash );
if ( $valid ) {
if ( password_needs_rehash ( $storedHash, PASSWORD_DEFAULT ) {
$newHash = password_hash( $passwordPresentedByUser, PASSWORD_DEFAULT );
/* UPDATE the user's row in the database to store $newHash */
}
/* log the user in, have fun! */
}
else {
/* tell the would-be user the username/password combo is invalid */
}
要解决散列问题,请尝试将这些代码行放入 php 程序中,看看会发生什么:
$myFakePassword = 'BompSheBomp!Wow';
$hash = password_hash( $myFakePassword, PASSWORD_DEFAULT );
var_dump( $hash );
$valid = password_verify ( $myFakePassword, $hash );
if ( $valid ) echo 'Hey! It worked!';
else echo 'WTF? password verify didn't work.';
然后确保在注册新用户时将散列密码存储在数据库中。当用户尝试登录时,请确保您使用 password_verify
来检查存储的、散列的密码是否与您的用户提供的密码。
您可以验证散列密码。但是你不能取消散列。
当我注册时,它对密码进行哈希处理,然后将用户名和哈希后的密码放入我的本地数据库中。工作正常。当我尝试登录时,用户名和密码与本地数据库中的任何一个都不匹配,它向我抛出名为 login=error2 的错误消息到 url,如果出现问题,我已经为这种情况编写了该消息那部分代码。所以你应该在 login.php 中寻找 error2。我认为问题就在那里。我整天都卡在上面,无法正常工作。
p.s。我是一名前端开发人员,我使用的最复杂的框架是 jquery 和 React,所以如果我对 php/mysql 听起来很愚蠢,我很抱歉。我在 3 天前开始学习 php。
我在 80 端口使用 XAMPP 本地主机, 这是我使用的 phpmyadmin sql 代码(数据库名称是 pixl_users)
创建tableuser_info( 用户名 varchar(12) 不为空, 密码 varchar(30), 电子邮件 varchar(30), 性别整数(1), 日期日期时间不为空 );
$(document).ready(function () {
//switch to login form
$('#switch-to-login').click(function () {
$('#form-register').hide();
$('#form-login').show();
});
//switch to registration form
$('#switch-to-signup').click(function () {
$('#form-login').hide();
$('#form-register').show();
});
});
========================================
signup.php file
<?php
if (isset($_POST['register'])) {
include_once 'db-connect.php';
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
if ((empty($username) || empty($password)) || $username == "admin" || $username == "Admin") {
// if fields are empty, send back to index and say error msg
header("Location: index.php?fields=empty");
exit();
} else {
// check for characters which are not allowed in the registration fields
if (!preg_match('/^[a-zA-Z0-9_.\s]+$/i', $username) || !preg_match('/^[a-zA-Z0-9_.!\s]+$/i', $password)) {
header("Location: index.php?fields=invalidcharacters");
exit();
} else {
//check if username is longer than 2 and shorter than 13 characters
if (strlen($username) > 2 && strlen($username) < 13) {
// check if username is taken
$sql = "SELECT * FROM user_info WHERE username='$username'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0) {
header("Location: index.php?fields=userTaken");
exit();
} else {
//hashing the password
$hashedPass = password_hash($password, PASSWORD_DEFAULT);
//insert the user into the database
$insert = "INSERT INTO user_info (username, password)
VALUES ('$username', '$hashedPass')";
//query it into the database
mysqli_query($conn, $insert);
//send user to the main website page
header("Location: index.php");
}
} else {
echo "Username can't be shorter than 3 characters and longer than 12 characters!";
}
}
}
}
login.php file
<?php
session_start();
if (isset($_POST['login'])) {
// connect to local database
include 'db-connect.php';
// get username and password from inputs
$username = mysqli_real_escape_string($conn, $_POST['login-username']);
$password = mysqli_real_escape_string($conn, $_POST['login-password']);
//check if fields are empty
if (empty($username) || empty($password)) {
header("Location: index.php?fields=empty");
exit();
} else {
// put usernames from table into array $resultCheck
$sql = "SELECT * FROM user_info WHERE username='$username'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
// if there is 0 usernames in database throw error
if ($resultCheck < 1) {
header("Location: index.php?login=error1");
exit();
} else {
if ($row = mysqli_fetch_assoc($result)) {
//De-hashing the password
$hashedPassCheck = password_verify($password, $row['password']);
if ($hashedPassCheck == false) {
header("Location: index.php?login=error2");
exit();
} elseif ($hashedPassCheck == true) {
// log in the user
$_SESSION['user_name'] = $row['username'];
header("Location: index.php?login=success");
exit();
}
}
}
}
} else {
header("Location: index.php?login=error");
exit();
}
<?php session_start(); ?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>database test</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<style>
body {
background-color: black;
color: white;
}
#form-register {
display: none;
}
</style>
</head>
<body>
<button id="switch-to-login">switch to login</button>
<button id="switch-to-signup">switch to signup</button>
<!-- register -->
<form id="form-register" action="signup.php" method="POST">
<input id="inp-username" type="text" name="username" placeholder="choose a name" /><br />
<input id="inp-password" type="password" name="password" placeholder="choose a password" />
<button id="btn-register" name="register" type="submit">Register</button>
</form>
<!-- login -->
<form id="form-login" action="login.php" method="POST">
<input id="inp-username" type="text" name="login-username" placeholder="login name" /><br />
<input id="inp-password" type="password" name="login-password" placeholder="password" />
<button id="btn-login" name="login" type="submit">Login</button>
</form>
<script src="script.js"></script>
</body>
</html>
如果您多次调用 $hash = password_hash($newRegistrantPassword, PASSWORD_DEFAULT)
,即使您输入的密码相同,您每次都会得到不同的 $hash
。那是因为该函数每次都会生成不同的随机散列。 (如果您对原因感到好奇,请查看 彩虹表 。)
如果您将 $hash
存储在没有足够字符的数据库列中,您将截断它。那很糟。 通过使用 VARCHAR(255)
作为散列密码来验证您的应用程序的未来。
面向未来是什么意思? php 开发人员认识到计算机变得更快,网络小鬼变得更聪明,密码更容易破解。所以他们添加了 password_needs_rehash()
function 。在 php 的未来版本中,他们可能会更改 PASSWORD_DEFAULT
哈希方法,使哈希更难破解。
对于期望寿命长的应用程序来说,好的密码验证码可能看起来像这样。
$valid = password_verify ( $passwordPresentedByUser, $storedHash );
if ( $valid ) {
if ( password_needs_rehash ( $storedHash, PASSWORD_DEFAULT ) {
$newHash = password_hash( $passwordPresentedByUser, PASSWORD_DEFAULT );
/* UPDATE the user's row in the database to store $newHash */
}
/* log the user in, have fun! */
}
else {
/* tell the would-be user the username/password combo is invalid */
}
要解决散列问题,请尝试将这些代码行放入 php 程序中,看看会发生什么:
$myFakePassword = 'BompSheBomp!Wow';
$hash = password_hash( $myFakePassword, PASSWORD_DEFAULT );
var_dump( $hash );
$valid = password_verify ( $myFakePassword, $hash );
if ( $valid ) echo 'Hey! It worked!';
else echo 'WTF? password verify didn't work.';
然后确保在注册新用户时将散列密码存储在数据库中。当用户尝试登录时,请确保您使用 password_verify
来检查存储的、散列的密码是否与您的用户提供的密码。
您可以验证散列密码。但是你不能取消散列。