Flask Application Session Handling With Redis

By Anurag Singh

Updated on Dec 02, 2024

Flask Application Session Handling With Redis

In this tutorial, we'll learn how to setup Flask application session handling with Redis on Ubuntu 24.04.

Efficient session management is critical in web applications. Using a database like MySQL for session storage can become a bottleneck as the application scales. By integrating Redis, an in-memory key-value store, you can significantly enhance session handling performance. This tutorial will guide you through implementing Redis-backed session management for a Python web application using Flask, MySQL, and Ubuntu 24.04.

Prerequisites

  • Ubuntu 24.04 installed on dedicated server or KVM VPS or local machine.
  • Python 3.10 or higher installed.
  • Familiarity with Python, Flask, and basic database operations.

Flask Application Session Handling With Redis

Step 1: Install and Configure Redis

Install Redis

Run the following commands to install Redis on Ubuntu:

sudo apt update
sudo apt install -y redis

Verify Redis Installation. Check the Redis server status:

sudo systemctl status redis

You should see the Redis service running. Test connectivity using the redis-cli:

redis-cli ping
# Expected output: PONG

Configure Redis for Production. Edit the Redis configuration file:

sudo nano /etc/redis/redis.conf

Set Redis to only listen on localhost:

bind 127.0.0.1

Enable persistence:

save 900 1
save 300 10
save 60 10000

Restart Redis to apply the changes:

sudo systemctl restart redis

Step 2: Set Up MySQL for User Authentication

Install MySQL

If MySQL is not already installed, run:

sudo apt install -y mysql-server

Secure MySQL Installation

Run the MySQL security script:

sudo mysql_secure_installation

Create a Database and Table for Users

Log in to MySQL and set up a database:

mysql -u root -p

Execute the following SQL commands:

CREATE DATABASE myapp;
USE myapp;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL
);

Create a user in MySQL:

INSERT INTO users (username, password_hash)
VALUES ('testuser', SHA2('password123', 256));

Step 3: Set Up Flask Application

Install Flask and Dependencies

Create a virtual environment for the project:

python3 -m venv myapp-env
source myapp-env/bin/activate

Install the required Python packages:

pip install flask flask-session mysql-connector-python redis

Flask Application Code

Create a file named app.py:

nano app.py

Add following code:

import hashlib
from flask import Flask, session, request, redirect, url_for
from flask_session import Session
import redis
from db import get_db_connection  # Import the database connection function

# Flask app setup
app = Flask(__name__)
app.secret_key = 'your-secret-key'

# Configure Redis for session storage
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_PERMANENT'] = False
app.config['SESSION_USE_SIGNER'] = True
app.config['SESSION_KEY_PREFIX'] = 'myapp:'
app.config['SESSION_REDIS'] = redis.StrictRedis(host='localhost', port=6379, db=0)

# Initialize session
Session(app)

@app.route('/')
def index():
    if 'username' in session:
        return f'Welcome {session["username"]}!'
    return 'You are not logged in. <a href="/login">Login</a>'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        db = get_db_connection()  # Establish the database connection
        cursor = db.cursor(dictionary=True)
        cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
        user = cursor.fetchone()
        cursor.close()
        db.close()

        if user and hashlib.sha256(password.encode()).hexdigest() == user['password_hash']:
            session['username'] = username
            return redirect(url_for('index'))

        return 'Invalid credentials. <a href="/login">Try again</a>'
    return '''
        <form method="post">
            Username: <input type="text" name="username"><br>
            Password: <input type="password" name="password"><br>
            <input type="submit" value="Login">
        </form>
    '''

@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))

if __name__ == '__main__':
    app.run(debug=True)

Note: If you want to start Flask application on public IP, use following code:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Next, create a db.py file for database connection:

nano db.py

Add following code:

import mysql.connector

def get_db_connection():
    return mysql.connector.connect(
        host="localhost",
        user="root",
        password="your-mysql-password",
        database="myapp"
    )

Step 4: Secure Redis and Application

Set Redis Authentication

Edit the Redis configuration file to set a password:

sudo nano /etc/redis/redis.conf

Uncomment and set the requirepass directive:

requirepass your_redis_password

Restart Redis:

sudo systemctl restart redis

Update your Flask configuration to include the Redis password:

app.config['SESSION_REDIS'] = redis.StrictRedis(
    host='localhost', port=6379, db=0, password='your_redis_password'
)

Use HTTPS for Flask in Production

Use a reverse proxy like Nginx to serve the Flask application over HTTPS.

Step 5: Test and Deploy the Application

Run the Flask application:

python app.py

Test Login and Session Handling:

Navigate your browser and access the Flask application using IP address. Log in with the username testuser and password password123.

Deploy to Production: Use a WSGI server like Gunicorn and reverse proxy via Nginx for production deployment.

Conclusion

In this tutorial, we've learnt how to setup Flask application session handling with Redis on Ubuntu 24.04. By integrating Redis with Flask for session storage, you can significantly improve the performance of session management in your Python/MySQL application. Redis's in-memory architecture ensures faster read/write operations, making it ideal for handling user sessions in high-traffic environments.