Skip to main content

Flask Sessions

Flask: Sessions

Flask sessions provide a mechanism to store user-specific data across multiple requests, enabling stateful interactions in web applications. Building on Flask Authentication, Flask User Registration, Flask User Login and Logout, Flask Password Hashing with Flask-Bcrypt, Flask Role-Based Access Control, Flask Protecting Routes with Flask-Login, Flask Managing User Sessions, Flask Querying the Database, and Flask Relationships in Models, Flask’s built-in session management complements Flask-Login for lightweight data storage. This tutorial explores Flask sessions, covering session creation, data storage, security, and integration with authentication, with practical applications in web development.


01. Why Use Flask Sessions?

Flask sessions allow developers to store temporary, user-specific data (e.g., user preferences, cart items, or temporary states) securely on the server side, using signed cookies. Combined with Flask-Login for authentication and NumPy Array Operations for efficient database queries, sessions enhance user experience in applications like e-commerce platforms, blogs, or dashboards by maintaining state without relying solely on database storage.

Example: Basic Flask Session Usage

from flask import Flask, session, redirect, url_for, request

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/set_session', methods=['POST'])
def set_session():
    username = request.form['username']
    session['username'] = username  # Store in session
    return redirect(url_for('get_session'))

@app.route('/get_session')
def get_session():
    username = session.get('username', 'Guest')
    return f"Welcome, {username}"

@app.route('/clear_session')
def clear_session():
    session.pop('username', None)  # Remove from session
    return redirect(url_for('get_session'))

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

Output:

Welcome, Alice (after POST to /set_session with username='Alice')
Welcome, Guest (after /clear_session)

Explanation:

  • session - A dictionary-like object for storing user-specific data.
  • SECRET_KEY - Signs session cookies to ensure security.
  • session.pop - Removes specific session data.

02. Key Flask Session Techniques

Flask sessions offer flexible tools for managing temporary user data. Below is a summary of key techniques and their applications in web applications:

Technique Description Use Case
Session Creation Store data in sessions Save user preferences
Session Retrieval Access stored session data Display user-specific content
Session Termination Clear session data Reset user state
Session Security Protect session data Prevent tampering
Session Integration Combine with Flask-Login Enhance authentication


2.1 Session Creation

Example: Storing User Preferences

from flask import Flask, session, request, redirect, url_for

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/set_preference', methods=['POST'])
def set_preference():
    theme = request.form['theme']
    session['theme'] = theme
    return redirect(url_for('show_preference'))

@app.route('/show_preference')
def show_preference():
    theme = session.get('theme', 'light')
    return f"Your selected theme: {theme}"

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

Output:

Your selected theme: dark (after POST to /set_preference with theme='dark')
Your selected theme: light (if no theme in session)

Explanation:

  • session['theme'] - Stores the user’s theme preference.
  • session.get - Retrieves data with a default value if not set.

2.2 Session Retrieval

Example: Accessing Session Data

from flask import Flask, session, redirect, url_for, request

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/set_user', methods=['POST'])
def set_user():
    session['user_id'] = request.form['user_id']
    return redirect(url_for('greet_user'))

@app.route('/greet_user')
def greet_user():
    user_id = session.get('user_id', 'Unknown')
    return f"Hello, user {user_id}"

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

Output:

Hello, user 123 (after POST to /set_user with user_id='123')
Hello, user Unknown (if no user_id in session)

Explanation:

  • session.get - Safely retrieves session data with a fallback.
  • Persists user-specific data across requests.

2.3 Session Termination

Example: Clearing Session Data

from flask import Flask, session, redirect, url_for

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/set_cart', methods=['POST'])
def set_cart():
    session['cart'] = ['item1', 'item2']
    return redirect(url_for('view_cart'))

@app.route('/view_cart')
def view_cart():
    cart = session.get('cart', [])
    return f"Cart: {cart}"

@app.route('/clear_cart')
def clear_cart():
    session.clear()  # Clear all session data
    return redirect(url_for('view_cart'))

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

Output:

Cart: ['item1', 'item2'] (after POST to /set_cart)
Cart: [] (after /clear_cart)

Explanation:

  • session.clear - Removes all session data, resetting the user’s state.
  • Useful for clearing temporary data like shopping carts.

2.4 Session Security

Example: Securing Flask Sessions

from flask import Flask, session, redirect, url_for, request
from datetime import timedelta

app = Flask(__name__)
app.config['SECRET_KEY'] = 'strong-secret-key-123'
app.config['SESSION_COOKIE_SECURE'] = True  # Requires HTTPS
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=30)

@app.route('/set_data', methods=['POST'])
def set_data():
    session['data'] = request.form['data']
    return redirect(url_for('get_data'))

@app.route('/get_data')
def get_data():
    data = session.get('data', 'No data')
    return f"Data: {data}"

if __name__ == '__main__':
    app.run(debug=True, ssl_context='adhoc')  # Enable HTTPS for testing

Output:

Data: test (after POST to /set_data with data='test')
Data: No data (if no session data or after timeout)

Explanation:

  • SECRET_KEY - Strong key for secure session signing.
  • SESSION_COOKIE_SECURE - Ensures sessions are sent over HTTPS.
  • SESSION_COOKIE_HTTPONLY - Prevents JavaScript access to session cookies.
  • SESSION_COOKIE_SAMESITE - Mitigates CSRF attacks.
  • PERMANENT_SESSION_LIFETIME - Sets session timeout to 30 minutes.

2.5 Session Integration with Flask-Login

Example: Combining Sessions with Flask-Login

from flask import Flask, session, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, current_user
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///integrated.db'
app.config['SECRET_KEY'] = 'your-secret-key'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(120), nullable=False)

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']
    user = User.query.filter_by(username=username).first()
    if user and bcrypt.check_password_hash(user.password_hash, password):
        login_user(user)
        session['last_page'] = request.form.get('last_page', '/dashboard')
        return redirect(session['last_page'])
    return "Invalid credentials"

@app.route('/dashboard')
@login_required
def dashboard():
    last_page = session.get('last_page', 'None')
    return f"Welcome, {current_user.username}, last visited: {last_page}"

with app.app_context():
    db.create_all()
    hashed_password = bcrypt.generate_password_hash('secure123').decode('utf-8')
    db.session.add(User(username='Charlie', password_hash=hashed_password))
    db.session.commit()

Output:

Welcome, Charlie, last visited: /dashboard (after login)

Explanation:

  • Uses Flask sessions to store temporary data (e.g., last visited page).
  • Integrates with Flask Managing User Sessions and Flask-Login for authentication.

2.6 Incorrect Session Usage

Example: Insecure Session Handling

from flask import Flask, session, request

app = Flask(__name__)
app.config['SECRET_KEY'] = 'weak'  # Insecure key

@app.route('/set_data', methods=['POST'])
def set_data():
    session['sensitive_data'] = request.form['data']  # No security flags
    return "Data set"

@app.route('/get_data')
def get_data():
    return f"Data: {session.get('sensitive_data', 'None')}"

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

Output:

Data: test (after POST to /set_data with data='test')
Data: None (if no session data)

Explanation:

  • Weak SECRET_KEY and missing security configurations (e.g., HTTPS) compromise session integrity.
  • Solution: Use a strong SECRET_KEY and secure session settings.

03. Effective Usage

3.1 Recommended Practices

  • Use Flask sessions for lightweight, temporary data and secure configurations.

Example: Comprehensive Session Usage

from flask import Flask, session, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from flask_bcrypt import Bcrypt
from datetime import timedelta

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///complete.db'
app.config['SECRET_KEY'] = 'secure-secret-key-123'
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=30)
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(120), nullable=False)

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']
    user = User.query.filter_by(username=username).first()
    if user and bcrypt.check_password_hash(user.password_hash, password):
        login_user(user, remember=True)
        session['theme'] = request.form.get('theme', 'light')
        return redirect(url_for('dashboard'))
    return "Invalid credentials"

@app.route('/logout')
@login_required
def logout():
    session.clear()  # Clear Flask session data
    logout_user()    # Clear Flask-Login session
    return redirect(url_for('home'))

@app.route('/dashboard')
@login_required
def dashboard():
    theme = session.get('theme', 'light')
    return f"Welcome, {current_user.username}, to your dashboard (Theme: {theme})"

@app.route('/home')
def home():
    return "Welcome to the homepage"

with app.app_context():
    db.create_all()
    hashed_password = bcrypt.generate_password_hash('secure123').decode('utf-8')
    db.session.add(User(username='Eve', password_hash=hashed_password))
    db.session.commit()

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

Output:

Welcome, Eve, to your dashboard (Theme: dark) (after login with theme='dark')
Welcome to the homepage (after logout)
  • Combines Flask sessions with Flask-Login for authentication and preferences.
  • Includes secure session configurations and timeout.
  • Clears both Flask and Flask-Login sessions on logout.

3.2 Practices to Avoid

  • Avoid storing sensitive data in sessions or using weak secret keys.

Example: Storing Sensitive Data

from flask import Flask, session, request

app = Flask(__name__)
app.config['SECRET_KEY'] = 'weak'

@app.route('/set_sensitive', methods=['POST'])
def set_sensitive():
    session['password'] = request.form['password']  # Insecure
    return "Data set"

@app.route('/get_sensitive')
def get_sensitive():
    return f"Password: {session.get('password', 'None')}"

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

Output:

Password: secret (after POST to /set_sensitive with password='secret')
Password: None (if no session data)
  • Storing sensitive data like passwords in sessions is insecure.
  • Solution: Use Flask Password Hashing with Flask-Bcrypt and avoid storing sensitive data.

04. Common Use Cases in Web Development

4.1 E-commerce Shopping Cart

Use sessions to store temporary shopping cart data for users.

Example: Shopping Cart Session

from flask import Flask, session, request, redirect, url_for

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/add_to_cart', methods=['POST'])
def add_to_cart():
    item = request.form['item']
    if 'cart' not in session:
        session['cart'] = []
    session['cart'].append(item)
    session.modified = True  # Mark session as modified
    return redirect(url_for('view_cart'))

@app.route('/view_cart')
def view_cart():
    cart = session.get('cart', [])
    return f"Cart: {cart}"

@app.route('/clear_cart')
def clear_cart():
    session.pop('cart', None)
    return redirect(url_for('view_cart'))

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

Output:

Cart: ['book', 'pen'] (after adding items)
Cart: [] (after /clear_cart)

Explanation:

  • Stores cart items in the session for temporary storage.
  • session.modified = True - Ensures list changes are saved.

4.2 User Preferences in Blogs

Store user preferences like theme or language in sessions.

Example: Blog Preferences Session

from flask import Flask, session, request, redirect, url_for

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/set_preferences', methods=['POST'])
def set_preferences():
    session['theme'] = request.form['theme']
    session['language'] = request.form['language']
    return redirect(url_for('blog'))

@app.route('/blog')
def blog():
    theme = session.get('theme', 'light')
    language = session.get('language', 'en')
    return f"Blog with theme: {theme}, language: {language}"

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

Output:

Blog with theme: dark, language: es (after POST to /set_preferences)
Blog with theme: light, language: en (if no session data)

Explanation:

  • Stores blog preferences in sessions for a customized experience.
  • Integrates with Flask Managing User Sessions for user tracking.

Conclusion

Using Flask sessions, integrated with Flask-Login, Flask Authentication, and NumPy Array Operations, provides a lightweight way to manage temporary user data. Key takeaways:

  • Use Flask sessions for temporary, non-sensitive data like preferences or carts.
  • Implement secure session configurations with HTTPS and timeouts.
  • Apply in e-commerce, blogs, or dashboards for personalized experiences.
  • Avoid storing sensitive data or using weak secret keys.

With these techniques, you can build Flask applications that efficiently manage user-specific data while maintaining security and scalability!

Comments