php - 我的 php 登录脚本无法正常工作
问题描述
我是 PHP 的初学者,我需要一个带有成员数据库的登录页面,所以我从教程中找到了一个脚本,但我不知道出了什么问题。
从 phpMyAdmin 我创建了一个名为“admin_logs”的数据库,然后创建了一个名为“registered_users”的表。但是当我在表格中输入用户然后尝试从网站登录时,它说我输入了无效的凭据。所以看起来我无法将数据发送到网站,但我不明白为什么:
索引.php
<?php
session_start();
if(!empty($_SESSION["userId"])) {
require_once './view/dashboard.php';
} else {
require_once './view/login-form.php';
}
?>
登录-action.php
<?php
namespace Phppot;
use \Phppot\Member;
if (! empty($_POST["login"])) {
session_start();
$username = filter_var($_POST["user_name"], FILTER_SANITIZE_STRING);
$password = filter_var($_POST["password"], FILTER_SANITIZE_STRING);
require_once (__DIR__ . "./class/Member.php");
$member = new Member();
$isLoggedIn = $member->processLogin($username, $password);
if (! $isLoggedIn) {
$_SESSION["errorMessage"] = "Invalid Credentials";
}
header("Location: ./index.php");
exit();
}
数据源.php
<?php
namespace Phppot;
/**
* Generic datasource class for handling DB operations.
* Uses MySqli and PreparedStatements.
*
* @version 2.3
*/
class DataSource
{
// PHP 7.1.0 visibility modifiers are allowed for class constants.
// when using above 7.1.0, declare the below constants as private
const HOST = 'localhost';
const USERNAME = 'root';
const PASSWORD = '';
const DATABASENAME = 'admin_logs';
private $conn;
/**
* PHP implicitly takes care of cleanup for default connection types.
* So no need to worry about closing the connection.
*
* Singletons not required in PHP as there is no
* concept of shared memory.
* Every object lives only for a request.
*
* Keeping things simple and that works!
*/
function __construct()
{
$this->conn = $this->getConnection();
}
/**
* If connection object is needed use this method and get access to it.
* Otherwise, use the below methods for insert / update / etc.
*
* @return \mysqli
*/
public function getConnection()
{
$conn = new \mysqli(self::HOST, self::USERNAME, self::PASSWORD, self::DATABASENAME);
if (mysqli_connect_errno()) {
trigger_error("Problem with connecting to database.");
}
$conn->set_charset("utf8");
return $conn;
}
/**
* To get database results
* @param string $query
* @param string $paramType
* @param array $paramArray
* @return array
*/
public function select($query, $paramType="", $paramArray=array())
{
$stmt = $this->conn->prepare($query);
if(!empty($paramType) && !empty($paramArray)) {
$this->bindQueryParams($stmt, $paramType, $paramArray);
}
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$resultset[] = $row;
}
}
if (! empty($resultset)) {
return $resultset;
}
}
/**
* To insert
* @param string $query
* @param string $paramType
* @param array $paramArray
* @return int
*/
public function insert($query, $paramType, $paramArray)
{
print $query;
$stmt = $this->conn->prepare($query);
$this->bindQueryParams($stmt, $paramType, $paramArray);
$stmt->execute();
$insertId = $stmt->insert_id;
return $insertId;
}
/**
* To execute query
* @param string $query
* @param string $paramType
* @param array $paramArray
*/
public function execute($query, $paramType="", $paramArray=array())
{
$stmt = $this->conn->prepare($query);
if(!empty($paramType) && !empty($paramArray)) {
$this->bindQueryParams($stmt, $paramType="", $paramArray=array());
}
$stmt->execute();
}
/**
* 1. Prepares parameter binding
* 2. Bind prameters to the sql statement
* @param string $stmt
* @param string $paramType
* @param array $paramArray
*/
public function bindQueryParams($stmt, $paramType, $paramArray=array())
{
$paramValueReference[] = & $paramType;
for ($i = 0; $i < count($paramArray); $i ++) {
$paramValueReference[] = & $paramArray[$i];
}
call_user_func(array(
'bind_param'
), $paramValueReference);
}
/**
* To get database results
* @param string $query
* @param string $paramType
* @param array $paramArray
* @return array
*/
public function numRows($query, $paramType="", $paramArray=array())
{
$stmt = $this->conn->prepare($query);
if(!empty($paramType) && !empty($paramArray)) {
$this->bindQueryParams($stmt, $paramType, $paramArray);
}
$stmt->execute();
$stmt->store_result();
$recordCount = $stmt->num_rows;
return $recordCount;
}
}
成员.php
<?php
namespace Phppot;
use \Phppot\DataSource;
class Member
{
private $dbConn;
private $ds;
function __construct()
{
require_once "DataSource.php";
$this->ds = new DataSource();
}
function getMemberById($memberId)
{
$query = "select * FROM registered_users WHERE id = ?";
$paramType = "i";
$paramArray = array($memberId);
$memberResult = $this->ds->select($query, $paramType, $paramArray);
return $memberResult;
}
public function processLogin($username, $password) {
$passwordHash = md5($password);
$query = "select * FROM registered_users WHERE user_name = ? AND password = ?";
$paramType = "ss";
$paramArray = array($username, $passwordHash);
$memberResult = $this->ds->select($query, $paramType, $paramArray);
if(!empty($memberResult)) {
$_SESSION["userId"] = $memberResult[0]["id"];
return true;
}
}
}
解决方案
我假设您只是在数据库中输入了一个带有明文密码的用户。(永远不要将纯文本密码存储在数据库中,因为手头的问题有一百万个原因。)现在,请注意文件processLogin()
中的以下行member.php
:
$passwordHash = md5($password);
$query = "select * FROM registered_users WHERE user_name = ? AND password = ?";
换句话说:您的登录系统正在使用用户名和 md5(密码)查询数据库,如果匹配,则认为登录有效。这意味着您将需要生成密码的 md5 哈希,并将其输入到数据库的密码字段中。
我想这就是您登录失败的原因。
我应该注意到 MD5 不是一种特别安全的散列方法。如今,SHA1 也不是替代品。您可能需要阅读PHP 密码常见问题解答。您可能希望将 替换为md5()
password_hash ()或crypt()函数,重要的是,为您的密码加盐。
即使您的用户数据库受到威胁,也$salt = 'r4nd0m57r1n6'; md5($password.$salt);
比直接安装要好。md5($password);
虽然不是很好,但考虑到计算量轻的 MD5 是如何破解的。(每秒数十亿次尝试。)至少当它被加盐时,它不是一个直接的彩虹表查找。