1

我从 W3Schools 网站上的几本书中自学了 PHP,并使用了 Stack Overflow 的一大堆帖子。

为了尝试将某些东西付诸实践,我正在尝试制作一个实现用户身份验证系统的小型图片库。用户具有确定他们是否具有读取、读写访问权限或可以管理其他用户等的安全访问权限。我只了解登录和添加用户内容。

我以我的工作为模型,每个人都有一个唯一的员工 ID 和 8 位数的电子邮件 ID。

我知道这是一个很长的镜头,但我只是想知道是否有人能够看一下并告诉我我的代码是否正朝着正确的方向前进?将这样的“现实世界”与书中提供的基本示例放在一起是非常不同的。任何意见和建议将不胜感激......

登录.php

<!DOCTYPE html>
<?php       
   // Connect to the database
   include('./helpers/db.php');
   include('./helpers/general.php');

   // Check if the user has submitted their details.
   if ($_SERVER['REQUEST_METHOD'] == 'POST') {
       $loginId = htmlspecialchars(($_POST['userId']));
       $loginPass = htmlspecialchars(sha1($_POST['password']));

       // Check if they've submitted blank details.
       if (!checkLoginId($loginId) || (!checkPassword($_POST['password']))) {
           $errorMsg = "Please enter a valid username or password!";
       }

       else {
       // Select the details we want for the session info.
       $stmt = $dbh->prepare("SELECT firstName, lastName, securityLevel FROM 
                            userDetails WHERE registeredNumber = :loginId 
                            AND password = :loginPass" );
       $stmt->bindParam(':loginId', $loginId);
       $stmt->bindParam(':loginPass', $loginPass);
       $stmt->execute();

            // Make sure the user is found, and that there security level is 1 or more.
            if ($stmt->rowCount() > 0) {
                $userDetails = $stmt->fetch();

                if ($userDetails['securityLevel'] < 1) {
                    $errorMsg = "Insufficient access for this user.";
                }

                else {

                // Start a new session and set up the regularly used info.
                session_start();
                $_SESSION['loggedIn'] = 1;
                $_SESSION['userID'] = $loginId;
                $_SESSION['fname'] = $userDetails['firstName'];
                $_SESSION['lname'] = $userDetails['lastName'];
                $_SESSION['security'] = $userDetails['securityLevel'];
                header("Location: ./browser/");
                }
            }

            else {
                $errorMsg = "Invalid User ID or Password!";
            }
       }
   }
?>

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
</head>
<style type="text/css">
       body {font-family:sans-serif;}
       .warning {color:red;font-weight:bold;}
       #login {margin-left:auto;margin-right:auto;width:200px;border-style:solid;border-width:1px;padding:20px;}
</style>
<body>
   <!-- Display the login form -->
    <div id="login">
        <form action="login.php" method="POST">
        <?php 
        if (isset($errorMsg)) {
            echo '<span class="warning">'. $errorMsg . '</span>';
        } 
        ?>
        <p><label for="userId">User Name:</label><br />
            <input type="text" maxlength="5" name="userId"
              title="Enter your User ID:">
        </p>
        <p><label for="pasword">Password:</label><br/>
            <input type="password" maxlength="12" name="password"
              title="Enter your password:"/>
        </p>
        <p><input id="submit" type="submit" name="submit" value="Submit"></p>
        </form>
    </div>
</body>

数据库.php

<?php
$hostname = 'localhost';
$dbname = 'dam';
$dbuser = 'root';
$dbpass = '****';

// Try and connect to the database and catch the error if it doesn't work.

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $dbuser, $dbpass);
    echo "Connected to Database<br/>";
}

catch (PDOException $e) 
{
    print "Error! " . $e->getMessage() . '<br/>';
    die();
}

?>

通用.php

<?php

// Checks wether the loginID/Registered Number is valid
function checkLoginId($login) {
if ($login == '' || $login == NULL || (!is_numeric($login))) {
    return 0;
}

else return 1;
}

// Checks whether the password is valid
function checkPassword($password) {
if ($password == '' || $password == NULL) {
    return 0;
}

else return 1;
}

function verifyNewUser($userID, $upass, $fname, $lname, $email) {
$hasErrors = 0;
$errorMsg = array();

if ($userID == '' || $userID == NULL || (!is_numeric($userID)) || (strlen($userID) != 5)) {
    $hasErrors++;
    $errorMsg[] = "User ID is either missing, or does not have 5 digits";
}

if ($upass == '' || $upass == NULL || (strlen($upass) <  6)) {
    $hasErrors++;
    $errorMsg[] = "Password is either missing, or does not meet minimum length of six";
}

if ($fname == '' || $fname == NULL || empty($fname)) {
    $hasErrors++;
    $errorMsg[] = "First name is missing.";
}

if ($lname == '' || $lname == NULL || empty($lname)) {
    $hasErrors++;
    $errorMsg[] = "Last name is missing.";
}

if ($email == '' || $email == NULL || empty($email) || (strlen($email) != 8)) {
    $hasErrors++;
    $errorMsg[] = "Check email id, should be 8 characters.";
}

if ($hasErrors == 0) {
    return 1;

}

else {
    echo "Returning with errors<br/>";
    return $errorMsg;
    } 
}
?>

添加用户.php

include ("./helpers/general.php");
include('./helpers/db.php');

session_start();

// If the user isn't logged in, send them away...
if (!(isset($_SESSION['loggedIn']) && $_SESSION['loggedIn'] != '')) {
header("Location: ./login.php");
exit();
}

// Get the users full name so we can politely tell them to rack off if they 
// don't have sufficient access to add users.
$uname = $_SESSION['fname'] . ' ' . $_SESSION['lname'];

// Check if the user has the security clearence to add a new user:
if ($_SESSION['security'] != 4) {
echo "Sorry $uname, only level 4 administrators can manage users.<br/>";
echo '<a href="./browser/">Back to Browser</a>';
exit();
}

// Check if they have submitted the form and validate the input
if ($_SERVER['REQUEST_METHOD'] == 'POST') {

$userID = htmlspecialchars($_POST['registeredNumber']);
$upass = htmlspecialchars($_POST['password']);
$fname = ucfirst(htmlspecialchars($_POST['firstName']));
$lname = ucfirst(htmlspecialchars($_POST['lastName']));
$email = htmlspecialchars($_POST['emailID']);
$secLev = $_POST['securityLevel'];
$creator = $_SESSION['userID'];

$valid = verifyNewUser($userID, $upass, $fname, $lname, $email);

if ($valid == 1) {
    // Encrypt the password
    $upass = sha1($upass);

    // Create the array to feed the SQL statement.
    $data = array($userID, $upass, $fname, $lname, $email, $secLev, date('Y-m-d H:i:s'), $creator);

    $dbh->beginTransaction();
    $stmt = $dbh->prepare("INSERT INTO userDetails VALUES('', ?, ?, ?, ?, ?, ?, ?, ?)");
    $stmt->execute($data);
    $dbh->commit();

    if ($stmt->rowCount() > 0) {
        echo "Success, new user $fname $lname added!<br/>";
        echo "Email ID: $email<br/>";
        echo "Security Level: $secLev<br/>";
    }
}    

else if (isset($valid)) {
    foreach($valid as $error) {
        echo '<span style="color:red;font-weight:bold">' . $error . "<span><br/>";
    }
}
}

?>

<!DOCTYPE html>
<html>
<head>
    <title>Add A New User</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
    <form action="adduser.php" method="post">
    <table>
        <tr>
            <td><label for="registeredNumber">Registered Number:</label></td>
            <td><input type="text" maxlength="5" name="registeredNumber"/></td>
        </tr>
        <tr>
            <td><label for="password">Password:</label></td>
            <td><input type="password" maxlength="12" name="password"/></td>
        </tr>
        <tr>
            <td><label for="firstName">First Name:</label></td>
            <td><input type="text" maxlength="20" name="firstName"/></td>
        </tr>
        <tr>
            <td><label for="lastName">Last Name:</label></td>
            <td><input type="text" maxlength="20" name="lastName"/></td>
        </tr>
        <tr>
            <td><label for="emailID">Email ID:</label></td>
            <td><input type="text" maxlength="8" name="emailID"/></td>
        </tr>
        <tr>
            <td><label for="securityLevel">Security Level:</label></td>
            <td>
                <select name="securityLevel">
                    <option value="0" selected="selected">0 - No Access</option>
                    <option value="1">1 - Read Access</option>
                    <option value="2">2 - Read/Write Access</option>
                    <option value="3">3 - Read/Write/Delete Access</option>
                    <option value="4">4 - User Administrator</option>
                </select>
            </td>
        </tr>
    </table>
    <input type="submit" name="submit" value="Submit"/>
    </form>
</body>
 </html>

注销.php

<?php

// Destroy the session and go to the login screen.
session_start();
session_destroy();
header("Location: login.php");
?>
4

1 回答 1

5

您的方法存在严重的安全问题。

最大的问题是您将密码存储在数据库中。您不需要将密码存储在数据库中,这是一个糟糕的主意,可能会成为有人在法庭上起诉您的理由。

有多种加密和散列选项可让您在不将密码存储在数据库中的情况下构建这样的系统,使用其中一种是标准程序。任何不这样做的人都在询问将来的问题(谷歌搜索“PSN 密码泄露”)。

一个不错的选择是 PBKDF2 http://en.wikipedia.org/wiki/PBKDF2

然而,这只是最明显的问题。还有一些其他的事情你做的并不完美,这确实是你需要学习如何正确做的事情,或者你根本不应该尝试。即使您使用的是 PBKDF2,您仍然需要学习如何正确使用它。

我建议在尝试编写自己的身份验证系统之前,几乎听完 Security Now 的每一集。http://www.grc.com/securitynow.htm

于 2012-10-05T04:07:01.163 回答