Flask Session and Cookie

HTTP protocol itself is stateless—the server won't automatically remember whether two requests come from the same user.

Flask viaSessionThe mechanism solves this problem, allowing web applications to "remember" user state.


How Session works

Flask uses by defaultSecureCookieSession, and the way it works is:

  • Session data is serialized, signed with a key, and stored in the browser's Cookie.
  • On each request, the browser automatically carries this Cookie.
  • After Flask verifies the signature, it restores the data to a Python dictionary for you to use.

Users can see the content in the Cookie (since it is base64-encoded), but they cannot tamper with it—because any modification will cause signature verification to fail.

Session 签名 Cookie 工作机制


Configure SECRET_KEY

To use Session, you must first set a secret key.SECRET_KEY— the secret key used for signing.

Example

import secrets
from flask import Flask

app = Flask(__name__)

# Generate a secure random key (only needs to be generated on the first run)
# secrets.token_hex() produces a 64-character hexadecimal random string
app.secret_key = secrets.token_hex()
# Or directly set a fixed value (convenient for development, but do not use it in production)
# app.secret_key = "dev-secret-key-change-in-production"

Important:SECRET_KEYIt must be kept secret and be sufficiently random. If the key leaks, anyone can forge your application's Session data. In production, read it from environment variables or configuration files—do not hardcode it in code.

Command to generate a high-quality key:

$ python -c 'import secrets; print(secrets.token_hex())'
192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf

Read and Write Session

sessionIt is a dictionary-like object, used basically the same as a Python dictionary:

Example

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

app = Flask(__name__)
app.secret_key = "dev-secret-key"

@app.route("/")
def index():
    # Check if the session contains username
    if "username" in session:
        return f"""
<h1>Welcome back, {session["username"]}!</h1>
<p>Your visit count: {session.get("visits", 0)}</p>
<p><a href="/logout">Logout</a></p>
        """


    return """
<h1>EXAMPLE Homepage</h1>
<p>You are not logged in yet.</p>
<p><a href="/login">Go to login</a></p>
    """


@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form.get("username", "")
        if username:
            # Store the username in the session
            session["username"] = username
            # Initialize visit count
            session["visits"] = 0
            return redirect(url_for("index"))

    return """
    <form method="post">
<h2>Log in to EXAMPLE</h2>
<p><input type="text" name="username" placeholder="Enter username"></p>
<p><input type="submit" value="Login"></p>
    </form>
    """


@app.route("/logout")
def logout():
    # Clear all data in session
    session.clear()
    # Or delete only a specific key:
    # session.pop("username", None)
    return redirect(url_for("index"))

Permanent Session

By default, Session becomes invalid after the browser closes (browser-session level).

If you need a "Remember Me" feature, you can mark the Session as permanent.Permanent (permanent):

Example

from datetime import timedelta

# Set the validity period of the permanent session (default 31 days)
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=7)

@app.post("/login-remember")
def login_remember():
    username = request.form.get("username")
    if username:
        session["username"] = username
        # Mark as permanent session, still valid after the browser is closed
        session.permanent = True
        return redirect(url_for("index"))

Message Flashing——One-time Messages

After the user submits the form, feedback messages such as "Operation successful" or "Error" need to be displayed.

For this kind of message that "disappears after being displayed once," Flask provides flash messages.flash()Mechanism.

Example

from flask import Flask, flash, get_flashed_messages, redirect, render_template, request, url_for

app = Flask(__name__)
app.secret_key = "dev-secret-key"

@app.route("/post", methods=["GET", "POST"])
def create_post():
    if request.method == "POST":
        title = request.form.get("title", "").strip()

        if not title:
            # Save error message to flash, categorized as "error"
            flash("Title cannot be empty", "error")
            return redirect(url_for("create_post"))

        # Save success message to flash, categorized as "success"
        flash(f"Article '{title}' published successfully!", "success")
        return redirect(url_for("create_post"))

    return render_template("create_post.html")

@app.route("/flash-demo")
def flash_demo():
    # Get all flashed messages (automatically cleared after reading)
    messages = get_flashed_messages(with_categories=True)
    return render_template("flash_demo.html", messages=messages)

Rendering flash messages in templates:

Example

<!-- File path: templates/create_post.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Publish Article - EXAMPLE</title>
    <style>
        .flash-success { color: green; background: #E8EEF5; padding: 10px; border-radius: 4px; }
        .flash-error { color: red; background: #ffebee; padding: 10px; border-radius: 4px; }
        .flash-info { color: blue; background: #e3f2fd; padding: 10px; border-radius: 4px; }
    </style>
</head>
<body>
    <h1>Publish Article</h1>

    <!-- Get and display all flash messages -->
    {% with messages = get_flashed_messages(with_categories=true) %}
        {% if messages %}
            {% for category, message in messages %}
                <div class="flash-{{ category }}">{{ message }}</div>
            {% endfor %}
        {% endif %}
    {% endwith %}

    <form method="post">
        <p>Title:<input type="text" name="title" style="width:300px;"></p>
        <p><input type="submit" value="Publish"></p>
    </form>
</body>
</html>
Category Recommended use cases
"message" (default) General notification
"success" Operation successful
"error" Operation failed
"warning" Warning message
"info" General information

Flash messages rely on Session, so you must set a secret key.SECRET_KEYOnly then can it be used.


Session FAQ

Cookie Size LimitNote: Browsers limit a single Cookie to about 4KB. Do not store large amounts of data in Session—it is suitable for lightweight information such as user IDs and preferences, not for files or large objects.

other extensions