I am currently learning PHP and decided to write a login and registration system to learn about error handling, mysql, password hashing and basic queries.
I know there's standard authentication systems with frameworks such as Laravel, but I wanted to write one myself just for learning purposes.
I'd like to get some feedback, based on:
- Security
- Code efficiency
- Unneeded code
- Code that slows the script
- Wrong use of functions
- Bad indentation
Security is of course the main thing here, if you have any other feedback please post it as it is greatly appreciated!
- SQL Injections
- XSS
- Session hijacking
My registering form
<?php
require('db.php');
if($_SERVER['REQUEST_METHOD'] == 'POST') {
// Throw error if a field is not filled in
if(empty($_POST['username']) || empty($_POST['password']) || empty($_POST['email'])) {
$err = "Vul alle velden in";
$class = "fail";
} else {
// If everything is filled in, prepare a statement
$stmt = $connect->prepare('INSERT INTO `users` (user_name, user_password, user_email, user_perms, user_created_at) VALUES (?, ?, ?, ?, ?)');
if($stmt) {
// If statement gets sent correctly, create variables and add them
$username = $_POST['username'];
// Hash users' password
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$email = $_POST['email'];
// Timestamp
$date = date('Y-m-d H:i:s');
// Standard user permission level
$perms = "Gebruiker";
// Bind parameters
$stmt->bind_param('sssss', $username, $password, $email, $perms, $date);
// Check whether query ran succesfully or not
if($stmt->execute()) {
$err = "Het account is aangemaakt";
$class = "succes";
} else {
$err = "Deze gebruikersnaam wordt al gebruikt";
$class = "fail";
}
}
}
}
?>
<!DOCTYPE html>
<html lang="en" dir="ltr" id="form-background">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="keywords" content="windows, windows server, linux, ubuntu, mint, install, guide, nnnext, click, tutorial, nextnextnext">
<meta name="description" content="Leer veel voorkomende installaties makkelijk met nextnextnext.click!">
<title>REGISTER</title>
<link rel="stylesheet" href="./css/nnnext-main.css">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="icon" href="./img/nnnext-favicon.ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="./css/nnnext-backend.css">
<link rel="stylesheet" type="text/css" href="./slick/slick.css"/>
<link rel="stylesheet" type="text/css" href="./slick/slick-theme.css"/>
</head>
<body>
<div class="admin-container form-background">
<div class="centered-form">
<form class="login-form" method="post">
<h3>REGISTER</h3>
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST') {
echo "<div class='error-handling " . $class . "'" . ">";
echo "<p>" . $err . "</p>";
echo "</div>";
}
?>
<input type="text" name="username" placeholder="Gebruikersnaam">
<input type="email" name="email" placeholder="Email adres">
<input type="password" name="password" placeholder="Wachtwoord">
<input type="submit" name="submit" value="Account aanmaken">
<p><a href="login.php">Ik heb al een account</a></p>
</form>
</div>
</div>
</body>
</html>
My login form
<?php
require('db.php');
// If the server receives a POST request
if($_SERVER['REQUEST_METHOD'] == 'POST') {
if(empty($_POST['username']) || empty($_POST['password'])) {
$err = "Vul beide velden in";
$class = "fail";
} else {
// If everything has been filled in, send the query to the server
$stmt = $connect->prepare('SELECT user_name, user_password, user_email, user_perms FROM `users` WHERE user_name = ?');
if($stmt) {
$username = $_POST['username'];
$password = $_POST['password'];
// Send parameters to the server
$stmt->bind_param('s', $username);
// Run statement
$stmt->execute();
// Get query result
$result = $stmt->get_result();
// Fetch the query result in a row and bind to variables
while($row = $result->fetch_assoc()) {
$hash = $row['user_password'];
$username = $row['user_name'];
$email = $row['user_email'];
$userPerms = $row['user_perms'];
}
// If there's no hash, the user does not exists
if(empty($hash)) {
$err = "Sorry, maar deze gebruik bestaat niet";
$class = "fail";
} else {
// Check whether password matches hash on server
if(password_verify($password, $hash)) {
// Hash matches password
session_start();
// Bind session variables
$_SESSION['username'] = $username;
$_SESSION['email'] = $email;
// Login succesful, set message and class accordingly
$err = "Succesvol ingelogt. Redirecting...";
$class = "succes";
// Redirect to secured page
header("Location: admin.php");
} else {
// Password doesn't match hash, set error message accordingly
$err = "Wachtwoord is incorrect";
$class = "fail";
}
}
}
}
}
?>
<!DOCTYPE html>
<html lang="en" dir="ltr" id="form-background">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="keywords" content="windows, windows server, linux, ubuntu, mint, install, guide, nnnext, click, tutorial, nextnextnext">
<meta name="description" content="Leer veel voorkomende installaties makkelijk met nextnextnext.click!">
<title>NNNEXT - INLOGGEN</title>
<link rel="stylesheet" href="./css/nnnext-main.css">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="icon" href="./img/nnnext-favicon.ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="./css/nnnext-backend.css">
<link rel="stylesheet" type="text/css" href="./slick/slick.css"/>
<link rel="stylesheet" type="text/css" href="./slick/slick-theme.css"/>
</head>
<body>
<div class="admin-container form-background">
<div class="centered-form">
<form class="login-form" method="post">
<form class="login-form" method="post">
<h3>Inloggen op nnnext.click</h3>
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST') {
echo "<div class='error-handling " . $class . "'" . ">";
echo "<p>" . $err . "</p>";
echo "</div>";
}
?>
<input type="text" name="username" placeholder="Gebruikersnaam">
<input type="password" name="password" placeholder="Wachtwoord">
<input type="submit" name="submit" value="Inloggen">
<p><a href="register.php">Ik heb nog geen account</a></p>
</form>
</div>
</div>
</body>
</html>
My authentication file
<?php
// Check whether session started or not
if(!isset($_SESSION)) {
session_start();
}
// Check whether user is logged in or not
if(!isset($_SESSION['username'])) {
header("Location: login.php");
exit();
}
?>
My logout file
<?php
// Check whether session started or not
if(!isset($_SESSION)) {
session_start();
}
// Destroy session and redirect to login page
if(session_destroy()) {
header("Location: login.php");
}
?>