Coding a secure login system using php and mysql
Updated: 16-May-2023 | Tags: PHP and MYSQL | Views: 6109
Introduction
Hi guys. In this tutorial we are going to create a secure login system with php and mysql.
We are gonna have a register page, a login page, a forgot password page, and an user account page where the user is going to be redirected when he logs in successfully.
Every input field will have a proper and secure validation, so you can easy implement the code in a live website.
Let's quickly see what we are going to encounter in this tutorial.
- We are going to connect to a database using the mysqli extension.
- We are going to log any database connection error in a log file. Its a big security risk if we print to the user connection errors.
- We are going to use mysql prepared statements when we query the database, so we don't need to worry of any SQL injection attack.
- We are gonna hash the password before we register the user in the database.
-
When the user forgets his password, we are gonna reset it in the database, and send him the new one.
We are going to use the reliable PHPMailer class library so we will be sure that our emails are going to be delivered. - When the user logs-in successfully, he will be redirected to his account page. In the account page the user has the option to log-out, or delete the account.
- And we are going to achieve all our tasks by writing and using functions.
Live demo
Below i have a live demo of the login system that we are going to code.
You can create a dummy account and play around with the demo. Make some errors, try to break the application.
If you enter an existing email you can check out the forgot password action. Don't worry your email will not be shared or used. In fact it will be deleted a few days later or so.
Go to the login page and log-in to your dummy account. Then logout or delete your account. Try out all the actions, you will have a better understanding on what we are going to code.
I hope you tried out the live example.
Now let's start building the application and see first the files that we need.
Project's folder
We need the following nine files to build our login system.
\-- root |-- index.php |-- login.php |-- forgot-password.php |-- account.php |-- delete-message.php |-- db-log.txt |-- config.php |-- functions.php |-- styles.css |-- PHPMailer/
- index.php... This will be our starting page and will contain the register form.
- login.php... we will have the login form.
- forgot-password.php... in here we will have the forgot-password form.
- account.php... in a successful login action this is the page that the user will be redirected.
- delete-message.php... When the user deletes his account he will be redirected to the delete-message.php page, which will contain a message that the account has been deleted.
- In the db-log.txt file we will log any database connection error that may occur.
- In the config.php file we will have our database connection details.
- function.php... in this file we are going to write all the functions that we will use to code the login system.
- We have a styles.css file to make our application pretty.
-
And last we have the PHPMailer folder. Download PHPMailer from Github, and add it to the project's folder.
This is all the files that we need, now let's start with our first file and that is the config.php file.
The config file
In the config.php file we will store the database's connection details, and the mail details that we are going to use in the PHPMailer library. This file is going to be included in the functions.php file.
<?php
session_start();
// Mysql server settings. ----------------------------------------------------
define('SERVER', 'localhost'); // Fill in your server's name.
define('USERNAME', ''); // Fill in your database username.
define('PASSWORD', ''); // Fill in your database password if any.
define('DATABASE', ''); // Fill in your database.
// PHPMailer settings. ------------------------------------------------------------
define('MAIL_HOST', 'mail.domain.com');
define('MAIL_USERNAME', 'info@domain.com');
define('MAIL_PASSWORD', 'email-account-password');
// Global variables -----------------------------------------------------------
define('WEBSITE_NAME', 'Digitalfox-tutorials');
-
In line 2 we are starting a session because later on when we log-in the user, we are going to store
his username in a session.
Next in line 3, 4, 5, and 6 we define the server, the mysql username, the mysql password, and the database that we are gonna use.
We can use the SERVER, USERNAME, PASSWORD, DATABASE constants, anywhere in our php code, even inside functions. Constants are global variables.
-
Set your smtp server like `mail.domain.com` or `smtp.mailserver.com`.
Example: If you want to send emails through Gmail the syntax is `smtp.gmail.com`. If you you want to send emails from your website the syntax is `mail.yourWebsite.com`.define('MAIL_HOST', 'mail.domain.com');
-
Set the email address that you use to log-in to your email account.
Note: The email address has to belong to the above MAIL_HOST.
define('MAIL_USERNAME', 'info@domain.com');
-
Set the password you use to log-in to the above email account.
Important!! If you use Gmail as your MAIL_HOST you have to turn on 2 factor authentication and create an App password and use it here instead of your actual google password.define('MAIL_PASSWORD', 'email-account-password');
Check out the google docs How to create a google app password
-
We define the website's name in a constant so we can use it anywhere in the application.
define('WEBSITE_NAME', 'Digitalfox-tutorials');
Now let's see the structure of our database table.
The users database table
In the database we are going to have a users table where we will register the users.
The table has four columns: a user_id, a username, a password and an email column.
Notice that the password is encrypted.
users_id | username | password | |
---|---|---|---|
1 | George | $2y$10$/P03OqfFtsvzaT88mW0G0uLHVtw6UH | somemail@mail.com |
If you download the source code you will get also the sql file with the users table structure.
Now let's build the application starting from the functions.php file, and write the functions we will need, to make the login system functional.
The functions php file
All the functions that we need to make the login system functional are gonna live in the functions.php file.
Let's see them.
- We are gonna have a connect() function, which will connect our application with the MySQL server and the database.
- We are gonna have a registerUser() function, which will insert the user in the database and in the users table.
- We are going to write a loginUser() function, to log-in the user.
- There will be a logoutUser() function to log-out the user.
- We are gonna have a passwordReset() function, to reset and send the user a new password if the user forgot his current one.
- And the last function will be the deleteAccount() function, if the user decides to close his account.
- As you see we are going to write six functions to make the login system to work.
- Lets begin.
The first thing that we are going to do in the functions.php file is to require the config file, because we need access to the database connection details.
<php
require "config.php";
The connect function
The first function that we are going to write is the connect function.
The connect function as the name implies will connect php and mysql.
function connect(){
The first thing that we do inside the connect function is to create a new mysqli object and connect the php language to the MySQL server. You see that we use the constants from the config file as arguments, and we store the returned object in the $mysqli variable.
$mysqli = new mysqli(SERVER, USERNAME, PASSWORD, DATABASE);
Next i am going to use an if statement and check the connect_errno property to see if the connection
was successful. connect_errno stands for "connect error number".
To have a successful connection the error number property must return a value of zero.
if($mysqli->connect_errno != 0){
If the returned value is not zero, "!= 0", we are going to log a message to the db-log.txt file.
$error = $mysqli->connect_error;
$error_date = date("F j, Y, g:i a");
$message = "{$error} | {$error_date} \r\n";
file_put_contents("db-log.txt", $message, FILE_APPEND);
return false;
- In line 5 we store the error that the MySQL server is throwing, in the $error variable.
- In line 6 we get the current date and time.
- In line 7 we combine the error message with the date and store them in the $message variable.
- Inline 8 we use the file_put_contents function to write the error message to the db-log.txt file.
- And in line 9 we return false and stop the function.
If, let's say, we use a wrong username and the connection fails, we will see the following line of code in the db-log.txt file.
Access denied for user 'wrong-username'@'localhost' (using password: YES) | September 22, 2022, 9:32 am
But if the connection is successful we are going to set the charset to "utf8mb4". This will ensure that the non Latin
languages are going to displayed correctly, in line 11.
And in line 12 we return the $mysqli object.
}else{
$mysqli->set_charset("utf8mb4");
return $mysqli;
} // end of if statement.
} // end of the connect function.
Now that we have the connect function let's write a function to register the user in the database and the users table.
The registerUser function
To register the user in the database we are going to write a function named registerUser,
and we are going to pass in the function four arguments.
function registerUser($email, $username, $password, $confirm_password){
Based on the form that we create later which is the same form from the live demo, we will have the following input fields as arguments: The users email, his username, his password, and a confirm password.
The first thing in the function to do, is to connect to the MySQL server and the database. So we are going to use the connect function, and store the returned mysqli object in the $mysqli variable.
$mysqli = connect();
Now we have access to the methods and properties of the mysqli object.
Next we will trim any white space from the beginning and the end of every argument.
$email = trim($email);
$username = trim($username);
$password = trim($password);
$confirm_password = trim($confirm_password);
The next step is to check if all fields have values.
$args = func_get_args();
foreach ($args as $value) {
if(empty($value)){
return "All fields are required";
}
}
- In line 23 we use the func_get_args function to get all the function's arguments. The function returns an array and we store it in the $args variable.
- We are going to use the foreach function to loop through the arguments and check if there is an empty value. if so we will return an error, and the registerUser function stops here.
Next we will loop again through the arguments and check if a value contains any open or closing tag characters (<>). This way we will avoid inserting any script tags in the database which will do us harm.
foreach ($args as $value) {
if(preg_match("/([<|>])/", $value)){
return "<> characters are not allowed";
}
}
We will use the preg_match function and if any value contains those characters we will return an error and stop the function here.
Next we are going to check if the user has entered a valid email.
if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
return "Email is not valid";
}
If the email entered is not valid, we will again return an error and the function will stop here.
Next we are going to search in the database and the users table if the email that the user entered already exists. We always check the database because there can not be two users having the same email.
$stmt = $mysqli->prepare("SELECT email FROM users WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$result = $stmt->get_result();
$data = $result->fetch_assoc();
if($data != NULL){
return "Email already exists, please use a different username";
}
- We are going to use mysql prepared statements to query the database. In fact we will do this in the whole tutorial.
- In line 33 to 37 we prepare and execute the query. I am not going to go through and explain how prepared statements are working, i have a tutorial about this topic that you can read How to write mysql prepared statements.
- In line 37 the $data variable is holding the result from our search query. If the $data variable holds the value of NULL this means that the email doesn't exists in the database. But if the $data variable is NOT NULL, that means that the email already exists in the users table and so we return an error and the function stops here.
Next we move to the username, and we will check the length.
if(strlen($username) > 100){
return "Username is to long";
}
If the username is greater than 100 characters then we return an error, and again we stop the function here.
Next we are going to check if the username exists in the users table, we want the username to be unique, we are going to do the same thing as we did with the email.
$stmt = $mysqli->prepare("SELECT username FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$data = $result->fetch_assoc();
if($data != NULL){
return "Username already exists, please use a different username";
}
If the username exists we return an error and stop the function here.
Next we are gonna move to the password and check its length.
if(strlen($password) > 255){
return "Password is to long";
}
If the password's length is greater than 255 characters, we will return an error and stop the function here.
Next we are going to check if the password is equal to the confirm password's value.
if($password != $confirm_password){
return "Passwords don't match";
}
If the two values don't match we return an error and stop the function here.
Next if we get so far without any errors we will encrypt the password before we store it in the users table.
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
If you are not familiar with password encryption, check this out. How to encode and decode JSON data using php
The last thing that we have to do is to insert the user to the users table.
We are going to use again a prepared statement and and if everything goes well we return the string "success", if not we return an error.
$stmt = $mysqli->prepare("INSERT INTO users(username, password, email) VALUES(?,?,?)");
$stmt->bind_param("sss", $username, $hashed_password, $email);
$stmt->execute();
if($stmt->affected_rows != 1){
return "An error occurred. Please try again";
}else{
return "success";
}
} // end of the registerUser function.
Everything the function returns will be displayed in the register form, if the condition meets.
Now that's all the code we have in the registerUser function, it was kind of big, if we want to add another validation action for a particular argument it is quite simple to do.
Now we are going to write a function to log-in the user.
The loginUser function
To log the user in we are going to write a function named loginUser. The loginUser function takes two arguments. The first argument is the user's username and the second argument is the user's password.
function loginUser($username, $password){
The first thing that we do inside the function is to connect to the database using the connect function in line 75.
$mysqli = connect();
$username = trim($username);
$password = trim($password);
In line 76 we trim any white space from the beginning and the end of the username and store the trimmed value to the $username variable. We do the same thing with the password in line 77.
Next we are going to check if both variables have values and are not empty.
if($username == "" || $password == ""){
return "Both fields are required";
}
If there is an empty value we return an error and stop the function here.
Next we are going to use the filter_var function with the FILTER_SANITIZE_FLAG to strip from any malicious characters the two values.
$username = filter_var($username, FILTER_SANITIZE_STRING);
$password = filter_var($password, FILTER_SANITIZE_STRING);
Next we are going to search in the database for the given username to check if the user exists.
Again we are going to use prepared statements to be as secure as we can.
If you are not familiar with prepared statements you can read this article. How to write mysql prepared statements
$sql = "SELECT username, password FROM users WHERE username = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$data = $result->fetch_assoc();
In line 82 the $data variable is holding the results from the query.
If the username exists, the $data variable will hold an array which will contain the username and the hashed password. But if the username do not exist in the database, the $data variable will have the value NULL.
if($data == NULL){
return "Wrong username or password";
}
So we will check the $data variable and if the value is equal to NULL we will return an error.
If the username is correct, we will verify that the incoming password is also the correct one.
if(password_verify($password, $data["password"]) == FALSE){
return "Wrong username or password";
}else{
$_SESSION["user"] = $username;
header("location: account.php");
exit();
}
} // end of loginUser function.
-
In line 88 we will use inside an if statement the password_verify function to check if the incoming password and the encrypted password from the database are the same.
The password_verify function takes in the first argument the incoming password, and in the second argument we have the encrypted password. The function will run it's encryption algorithm and will return TRUE if the two passwords match, or FALSE if not.
If the function returns FALSE we return an error in line 89.
The password_verify function can verify a password only if the password were encrypted with the password_hash function. Those two functions are working together.
And we did used the password_hash function in the registerUser function. - Else if the user has given the correct password we set a user session and store the users username, in line 91.
-
And in line 92-93 we redirect the user to his account page and exit() the script.
That was the loginUser function, the next function that we are gonna write is the logoutUser.
The logoutUser function
The logoutUser function is the most easy one inside our functions file.
When the function runs the user session will be destroyed and the user will be redirected to the login.php page. In your application
you can redirect the user in any page you like.
function logoutUser(){
session_destroy();
header("location: login.php");
exit();
}
The next function is the passwordReset function.
The passwordReset function
The passwordReset function will reset the password in the users table and will send the new password to the user. The function takes one argument and that is the users email address.
function passwordReset($email){
Again we will use the connect function to connect to the MySQL server, and trim any white space left and right from the given email.
$mysqli = connect();
$email = trim($email);
Next we are going to check if the user has entered a valid email.
if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
return "Email is not valid";
}
We are gonna use the filter_var function, but this time we use the FILTER_VALIDATE_EMAIL flag.
The function returns FALSE if not a valid email structure is given. If this is the case we return an error message.
Next as we always do when we query the database we are going to use a prepared statement to check if the given email exists in the database.
$stmt = $mysqli->prepare("SELECT email FROM users WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$result = $stmt->get_result();
$data = $result->fetch_assoc();
In line 115 the $data variable is holding the query results.
If the email doesn't exists in the users table, the $data variable will have a value of NULL.
If this is the case we return an error.
if($data == NULL){
return "Email doesn't exist in the database";
}
If the email exists we are going to create a random password which will be seven characters long.
$str = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcefghijklmnopqrstuvwxyz";
$password_length = 7;
$new_pass = substr(str_shuffle($str), 0, $password_length);
- In line 121 we have a string that contains all the English alphabet, upper and lower case, and the numbers from 1 to 10.
- In line 122 we are setting the password's length.
- And in line 123 we shuffle the string and we take from the string the first seven characters and store them in the $new_pass variable.
Next we are going to hash the password, so we can update the old password in the database.
$hashed_password = password_hash($new_pass, PASSWORD_DEFAULT);
Next we are going to use again a prepared statement to update the password in the users table.
$stmt = $mysqli->prepare("UPDATE users SET password = ? WHERE email = ?");
$stmt->bind_param("ss", $hashed_password, $email);
$stmt->execute();
if($stmt->affected_rows != 1){
return "There was a connection error, please try again.";
}
In line 129 we check if the update query was successful. If not we return an error.
Next we are going to use the PHPMailer class library to send the password to the user.
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = MAIL_HOST; // The mail host that we have defined in the config file.
$mail->SMTPAuth = true;
$mail->Username = MAIL_USERNAME; // Username (email) defined in the config file.
$mail->Password = MAIL_PASSWORD; // Password defined in the config file.
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
// Recipients
$mail->setFrom(MAIL_USERNAME, WEBSITE_NAME);
$mail->addAddress($email);
$mail->Subject = 'Password Recovery';
$mail->Body = "You can log in with your new password : {$new_pass}";
// checking if the mail was sent.
if(!$mail->send()){
return "Email not send. Please try again";
}else{
return "success";
}
} // end of passwordReset function.
And we are finished with the passwordReset function. Now let's go to write our last function in the file, which is the deleteAccount function.
The deleteAccount function
With the deleteAccount function we give the user the option to delete his account. Which basically is to delete his username, his email and password from the database.
function deleteAccount(){
Again we are going to use the connect function to connect to the database.
$mysqli = connect();
Next we are going to use a prepared statement to delete the user from the database.
$sql = "DELETE FROM users WHERE username = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("s", $_SESSION['user']);
$stmt->execute();
We will search the users table for the user's username.
Remember that every username in the users table is unique, so we will be sure that we delete the correct user. Now the username is stored in a session because the user is already logged in, else he wouldn't have access to the delete account action.
So we are going to use that session to find the user.
And last we are gonna check the affected_rows property, and if the returned value is not one, we return an error. Else we destroy the user's session and redirect him to the delete-message.php page, which will display a confirmation message.
if($stmt->affected_rows != 1){
return "An error occurred. Please try again";
}else{
session_destroy();
header("location: delete-message.php");
exit();
}
} // end of the deleteAccount function.
In this point we are done with the functions.php file.
Now let's write the html forms that corresponds to every function. And let's
begin with the register form.
The register form
We re gonna have the register form in the index.php file. When the application runs this will be our first screen.
In every form at the top of the page we are going to have a php code-block in which we are going to require the functions.php file so we have access to our functions there.
<?php
require "functions.php";
if(isset($_POST['submit'])){
$response = registerUser($_POST['email'], $_POST['username'], $_POST['password'], $_POST['confirm-password']);
}
?>
- Next in line 3 we are going to check if the form is submitted.
-
If the form is submitted, that means that we are inside the if statement.
So we are going to run the registerUser function and pass-in the arguments that are required. The arguments are the user's email, the username, the password and the confirm-password value.
We are going to store whatever the function returns in the $response variable.
Next we are going to have the html code for the register form.
The important thing here is that we set in the input value attributes the posted values that the $_POST variable holds when the form is submitted.
In this way we won't lose what we have typed in the fields when there is an error. This is also called a sticky form. The @ character in front of the $_POST variables tells the browser not to throw a warning when the page loads.
<form action="" method="post">
<label>Email *</label>
<input type="text" name="email" value="<?php echo @$_POST['email']; ?>" >
<label>Username *</label>
<input type="text" name="username" value="<?php echo @$_POST['username']; ?>" >
<label>Password *</label>
<input type="text" name="password" value="<?php echo @$_POST['password']; ?>">
<label>Confirm Password *</label>
<input type="text" name="confirm-password" value="<?php echo @$_POST['confirm-password']; ?>">
<button type="submit" name="submit">Submit</button>
In line 21 we have the submit button. The submit button's name attribute, is the value that we check in the php code at the top of the page, if the form is submitted.
Next and under the submit button we are gonna have the error and success messages.
<?php
if(@$response == "success"){
?>
<p class="success">Your registration was successful</p>
<?php
}else{
?>
<p class="error"><?php echo @$response; ?></p>
<?php
}
?>
</form> <!-- end of register form -->
We are gonna check the $response variable that the registerUser function returns, and if the value is the string "success", we display a success message. Else we display the error.
Now let's move to the login form
The login form
Again we are going to have our php code-block at the top of the page in which we require the functions.php file so we can have access to the loginUser function.
<?php
require "functions.php";
if(isset($_POST['submit'])){
$response = loginUser($_POST['username'], $_POST['password']);
}
?>
Again we are going to check if the form is submitted, and if this is the case we are going to run the userLogin function.
The function takes two arguments the user's username and password. And we store the returned value to the $response variable. We do the same thing here as we did in the register page.
In the login form we set the submitted values that the $_POST variable holds to the value attributes. We did the same thing in the register form, so we not lose the values that we type in when there is an error.
<form action="" method="post">
<label>Username</label>
<input type="text" name="username" value="<?php echo @$_POST['username']; ?>">
<label>Password</label>
<input type="text" name="password" value="<?php echo @$_POST['password']; ?>">
<button type="submit" name="submit">Submit</button>
<p class="error"><?php echo @$response; ?></p>
</form>
In line 16 we display any error that may occur. Notice that we don't have here a success message. That is because we redirect the user to the account.php page when he logs in successfully.
Next we will write the forgot password form.
The forgot-password form
We have the same pattern here as well. We require the functions.php file and check if the form is submitted.
<?php
require "functions.php";
if(isset($_POST['submit'])){
$response = passwordReset($_POST['email']);
}
?>
If the form is submitted, we are gonna run this time the passwordReset function. The function takes as a single argument the user's email address.
In the forgot password form we have only one field and that is the email. We set the input's value attribute to the submitted value as we did in the other two forms.
<form action="" method="post">
<label>Email</label>
<input type="text" name="email" value="<?php echo @$_POST['email']; ?>">
<button type="submit" name="submit">Submit</button>
And again we check the $response variable to see if the function succeeded or there was an error.
<?php
if(@$response == "success"){
?>
<p class="success">Please go to your email account and use your new password.</p>
<?php
}else{
?>
<p class="error"><?php echo @$response; ?></p>
<?php
}
?>
</form>
Now let's go to the account.php page.
The user account page
The account.php page is the page that the user is redirected if he logs in successfully. Again we are going to have our php code-block at the top of the page, but it will look a little bit different than the code-block that we had on the other pages.
<?php
require "functions.php";
if(!isset($_SESSION['user'])){
header("location: login.php");
exit();
}
if(isset($_GET['logout'])){
logoutUser();
}
if(isset($_GET['confirm-account-deletion'])){
deleteAccount();
}
?>
- in line 2 we require the functions.php file.
- In line 3 we have an if statement and we will check if the user is loged-in, else we redirect him to the login.php screen. We are doing this to make sure that the account page is secure. Only if a user is loged-in can have access to this page.
- In this page the user has the options to perform two actions.
- The first action is to logout, so in line 8 we are gonna check if the user clicked on a logout link that we are gonna have in the page, and if so, we are going to execute the logoutUser function.
- The second option for the user is to click on the delete account link. In this case we are going to ask him again if he is sure that he wants to delete his account. And if he confirm, we have an if statement in line 12 to catch the confirmation and to execute the deleteAccount function, in line 13.
Now let's see the account.php file's html code.
<h2>Welcome <?php echo $_SESSION["user"] ?></h2>
<h4>This is a secure page</h4>
<a href="?logout">Logout</a>
<?php
if(isset($_GET['delete-account'])){
?>
<p class="confirm-deletion">
Are you sure you want to delete you account?
<a href="?confirm-account-deletion">Delete account</a>
</p>
<?php
}else{
?>
<a href="?delete-account">Delete account</a>
<?php
}
?>
- In line 17 we use the user session to welcome the user.
- In line 20 we have the logout link. The "?logout" query string means that we send a GET request to the same page. If you go to line 8, you will see that we are capturing the "logout" key to log-out the user.
-
In line 23 we use an if statement that says: If the user clicks on the delete account link on line 32, we show the confirm message. And
if the user clicks on the delete account link on line 27, then we delete his account on line 13.
Hope it makes sense.
The CSS code
In the css file we have the exact same styling rules as you saw in the live demo.
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
font-family: sans-serif;
min-height: 100vh;
color: #555;
padding-top: 30px;
}
form, .page{
max-width: 90%;
border: thin solid #e4e4e4;
padding: 20px 40px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
margin: 0 auto;
}
form h2, .page h2{
font-size: 32px;
line-height: 52px;
color: #555;
margin-bottom: 5px;
}
form h4, .page h4{
margin-bottom: 30px;
padding-bottom: 10px;
border-bottom: thin solid #e4e4e4;
line-height: 26px;
}
form h4 span{
color: #af0c0c;
font-weight: normal;
}
form > div{
margin-bottom: 20px;
}
form .grid{
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 50px;
}
form label{
display: block;
margin-bottom: 10px;
padding-left: 5px;
}
form input{
display: block;
width: 100%;
padding: 10px;
margin-bottom: 10px;
font-size: 16px;
border: thin solid #e4e4e4;
margin-bottom: 30px;
border-radius: 5px;
}
form input:focus
{
outline: none;
}
form button{
background: #32749a;
color: white;
border: none;
padding: 10px 30px;
font-size: 16px;
cursor: pointer;
border-radius: 5px;
margin-bottom: 10px;
}
form button:active{
background-color: green;
}
form p{
margin-top: 15px;
}
form p a{
display: inline-block;
color: #006dbc;
text-decoration: none;
}
form p a:hover{
text-decoration: underline;
}
.page a{
display: inline-block;
color: #006dbc;
margin-top: 20px;
}
a.confirm-deletion{
text-decoration: none;
color: red;
margin-left: 10px;
}
.error{
margin-top: 30px;
color: #af0c0c;
line-height: 26px;
}
.success{
margin-top: 30px;
color: green;
}
Summary
In this tutorial we saw how to code a secure register and login system using PHP and MySQL.
This is a quite lengthy tutorial, please let me know if
everything is understandable.
Thanks for reading, i hope you find the article helpful.
Please leave a comment if you find any errors, so i can update the page with the correct code.
Source code
If you fell like avoiding all the copying and pasting,
you can buy me a coffee and
Get the source code
in a zip file.
The code is double and triple checked and works fine.
But be sure before you download the source code, that you have a local server installed.
If you download the source code, please go to the config.php file first to set your settings
Buy me a coffee
Tutorial Categories
Comment section
You can leave a comment, it will help me a lot.
Or you can just say hi. 😉