Introduction
Authentication is the process of verifying users’ identity during login requests. In an authentication process, users submit their credentials as usernames and passwords. Then, the application matches those login credentials with stored database entries. The application grants users access to the system if there is a match.
Storing login credentials in a relational database like MySQL or PostgreSQL without a caching mechanism is still a common and practical approach, but it comes with the following limitations:
-
Overloading the database. The application must make a roundtrip to the database server to verify the users’ credentials from a database table every time a user submits a login request. Because the database might still serve other read/write requests, the entire process overloads the database and makes it slow.
-
Traditional disk-based databases have scalability issues. When your application receives thousands of requests per second, disk-based databases do not perform optimally.
To overcome the above challenges, you can use Redis to cache the users’ login credentials so that your application doesn’t have to contact the backend database during each login request. Redis is one of the most popular ultrafast data stores that utilizes your computer’s RAM to store data in key-value pairs. In this guide, you’ll use the Redis database to speed up session handling in your Python/MySQL application on the Ubuntu 22.04 server.
Prerequisites
Before you begin this tutorial, you will need to setup following:
-
Switch to the new
sudo
user account and install:
Step 1 — Installing Python Database Drivers for Redis and MySQL
This application permanently stores users’ credentials, such as names and passwords, in a MySQL database server. When a user logs in to the application, a Python script queries the MySQL database and matches the details with stored values. Then, the Python script caches the user’s login credentials in a Redis database to serve other future requests. To complete that logic, your Python scripts require database drivers (Python modules) to communicate with the MySQL and Redis servers. Follow the steps below to install the drivers:
- Update your package information index and run the following command to install
python3-pip
, a Python package manager allowing you to install additional modules not part of the Python standard library.
- Install the MySQL driver for Python:
- Install the Redis driver for Python:
After installing the necessary drivers for communicating with MySQL and Redis, proceed to the next step and initialize a MySQL database.
Step 2 — Setting Up a Sample MySQL Database
For this guide, you require one MySQL table. In a production environment, you can have dozens of tables that serve other requests. Set up a database and create the table by executing the following commands:
-
Log in to the MySQL database server as a
root
user: -
Enter your MySQL server’s
root
password when prompted and pressENTER
to proceed. Then, run the following command to create a samplecompany
database and acompany_user
account. Replaceexample-mysql-password
with a strong password:
-
Ensure you receive the following output to confirm that the previous commands have run successfully:
-
Switch to the new
company
database: -
Confirm you’re connected to the new database by verifying the following output:
-
Create a
system_users
table. Theuser_id
column serves as aPRIMARY KEY
to uniquely identify each user. Theusername
andpassword
columns are the login credentials that users must submit to log in to the application. Thefirst_name
andlast_name
columns store the users’ names: -
Ensure you’ve created the new table by verifying the following output:
-
Populate the
system_users
table with sample data. Use the MySQL inbuiltMD5(...)
function to hash the password for security purposes: -
Verify the output below:
-
Query the
system_users
table to ensure the data is in place: -
Verify the following output:
-
Log out from the MySQL database:
You’ve now set up the right MySQL database for your application. In the next step, you’ll build a Python module communicating with your sample database.
Step 3 — Creating a Central MySQL Gateway Module for Python
When coding any Python project, you should create a separate module for each task to promote code reusability. In this step, you’ll set up a central module that allows you to connect and query the MySQL database from a Python script. Follow the steps below:
-
Create a
project
directory. This directory separates your Python source code files from the rest of the system files: -
Switch to the new
project
directory: -
Use
nano
text editor to open a newmysql_db.py
file. This file hosts the Python module that talks to the MySQL database: -
Enter the following information into the
mysql_db.py
file. Replaceexample-mysql-password
with the correct MySQL password for thecompany_user
account:~/project/mysql_db.py -
Save and close the
mysql_db.py
file.
The mysql_db.py
module file has one class (MysqlDb:
) with two methods:
– db_con(self):
, connects to the sample company
database that you created earlier and returns a reusable MySQL connection using the return mysql_con
statement.
– query(self, username, password):
, a method that accepts a username
and password
and queries the system_users
table to find if there is a match. The conditional if row_count < 1: ... else: return result[1]
statement returns the boolean False
value if a user doesn’t exist in the table or the user’s password (result[1]
) if the application finds a match.
With the MySQL module ready, follow the next step to set up a similar Redis module that communicates to the Redis key-value store.
Step 4 — Creating a Central Redis Module for Python
In this step, you’ll code a module that connects to the Redis server. Execute the following steps:
-
Open a new
redis_db.py
file: -
Enter the following information into the
redis_db.py
file. Replaceexample-redis-password
with the correct password for the Redis server:~/project/redis_db.py -
Save and close the
redis_db.py
file.
-
The above file has one class (
RedisDb:
). -
Under this class, the
db_con(self):
method uses the provided credentials to connect to the Redis server and returns a reusable connection using thereturn redis_con
statement.
After setting up the Redis class, create the main file for your project in the next step.
Step 5 — Creating the Application’s Entry Point
Every Python application must have an entry point or the main file that executes when the application runs. In this file, you’ll create a code that shows the current server’s time for authenticated users. This file uses the custom MySQL and Redis modules you created to authenticate users. Follow the steps below to create the file:
-
Open a new
index.py
file: -
Enter the following information into the
index.py
file:~/project/index.py -
Save and close the
index.py
file.
-
In the
index.py
file, theimport...
section adds the following modules to your project:-
utf_8
,base64
,md5
, andjson
, text encoding and formatting modules. -
http.server
,HTTPStatus
, andsocketserver
, web server modules. -
datetime
, time/date module. -
mysql_db
andredis_db
, custom modules that you previously created to access the MySQL and Redis servers.
-
-
The
HttpHandler(http.server.SimpleHTTPRequestHandler):
is a handler class for the HTTP server. Under the class, thedo_GET(self):
method servers the HTTP GET requests and displays the system’s date/time for authenticated users. -
In the
if ... : else: ...
logic, the Python script runs the logicalif redis_client.exists(auth_user):
statement to check if the user’s credentials exist in the Redis server. If the user details exist and the Redis stored password doesn’t match the user’s submitted password, the application returns the{"error": "Invalid username/password."}
error.
If the user details do not exist in the Redis server, the application queries the MySQL database server using the mysql_resp = mysql_server.query(auth_user, auth_password)
statement. In case the user’s supplied password doesn’t match the database stored value, the application returns the {"error": "Invalid username/password."}
error. Otherwise, the application caches the user’s details in the Redis server using the redis_client.set(auth_user, mysql_resp)
statement.
-
In all cases where the user’s credentials match the Redis/MySQL details, the application displays the system’s current date/time using the
{"time": current_time, ...}
statement. Theauthorized by
entry in the output allows you to see the database server that authenticates the users in the application.
You have now set up the main file for the application. In the next step, you’ll test the application.
Step 6 — Testing the Application
In this step, you’ll run your application to see if the Redis caching mechanism works. Execute the commands below to test the application:
-
Use the following
python3
command to run the application: -
Ensure the application’s custom web server is running:
-
Establish another
SSH
connection to your server in a new terminal window and run the followingcurl
commands to send four GET request usingjohn_doe's
credentials. Append[1-4]
at the end of thehttp://localhost:8080/
URL to send the four requests in a single command: -
Verify the following outputs. The MySQL server only serves the first authentication request. Then, the Redis database serves the next three requests.
Your application logic is now working as expected.
Conclusion
In this guide, you built a Python application that uses the Redis server to cache users’ login credentials. Redis is a highly available and scalable database server that can perform thousands of transactions per second. With the Redis caching mechanism in your application, you can highly reduce traffic in your backend database server. To learn more about Redis applications, refer to our Redis tutorials .