Сессия и Cookie во Flask
Сам протокол HTTP не имеет состояния — сервер не будет автоматически запоминать, приходят ли два запроса от одного и того же пользователя.
Flask с помощьюсессий— этот механизм решает эту проблему, позволяя веб-приложениям "запоминать" состояние пользователя.
Как работает Session
Flask по умолчанию используетSecureCookieSession, и принцип его работы таков:
- Данные Session сериализуются, подписываются ключом и сохраняются в Cookie браузера.
- При каждом запросе браузер автоматически передаёт этот Cookie.
- После проверки подписи Flask восстанавливает данные в словарь Python, который вы можете использовать.
Пользователи могут видеть содержимое Cookie (поскольку оно закодировано в base64), но не могут его подделать — потому что любое изменение приведёт к сбою проверки подписи.
Настройка SECRET_KEY
Чтобы использовать Session, сначала нужно задать секретный ключ.SECRET_KEY— секретный ключ, используемый для подписи.
Пример
from flask import Flask
app = Flask(__name__)
# Сгенерируйте безопасный случайный ключ (нужно сгенерировать только при первом запуске)
# secrets.token_hex() создаёт 64-символьную шестнадцатеричную случайную строку
app.secret_key = secrets.token_hex()
# Или напрямую задайте фиксированное значение (удобно для разработки, но не используйте его в продакшене)
# app.secret_key = "dev-secret-key-change-in-production"
Важно:SECRET_KEYЕго необходимо держать в секрете, и он должен быть достаточно случайным. Если ключ утечёт, любой сможет подделать данные сессии вашего приложения. В продакшене читайте его из переменных окружения или файлов конфигурации — не прописывайте его жёстко в коде.
Команда для генерации высококачественного ключа:
$ python -c 'import secrets; print(secrets.token_hex())' 192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf
Чтение и запись сессии
sessionЭто объект, подобный словарю, используется в основном так же, как словарь Python:
Пример
app = Flask(__name__)
app.secret_key = "dev-secret-key"
@app.route("/")
def index():
# Проверить, содержит ли session username
if "username" in session:
return f"""
<h1>С возвращением, {session["username"]}!</h1>
<p>Ваше количество посещений: {session.get("visits", 0)}</p>
<p><a href="/logout">Выйти</a></p>
"""
return """
<h1>ПРИМЕР Домашняя страница</h1>
<p>Вы ещё не вошли в систему.</p>
<p><a href="/login">Перейти к входу</a></p>
"""
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form.get("username", "")
if username:
# Сохранить имя пользователя в сессии
session["username"] = username
# Инициализировать счётчик посещений
session["visits"] = 0
return redirect(url_for("index"))
return """
<form method="post">
<h2>Войти в EXAMPLE</h2>
<p><input type="text" name="username" placeholder="Введите имя пользователя"></p>
<p><input type="submit" value="Войти"></p>
</form>
"""
@app.route("/logout")
def logout():
# Очистить все данные в сессии
session.clear()
# Или удалить только конкретный ключ:
# session.pop("username", None)
return redirect(url_for("index"))
Постоянная сессия
По умолчанию сессия становится недействительной после закрытия браузера (на уровне сессии браузера).
Если вам нужна функция "Запомнить меня", вы можете пометить сессию как постоянную.Постоянная (permanent):
Пример
# Установить срок действия постоянной сессии (по умолчанию 31 день)
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
# Пометить сессию как постоянную, она остаётся действительной после закрытия браузера
session.permanent = True
return redirect(url_for("index"))
Flash-сообщения——одноразовые сообщения
После того как пользователь отправит форму, необходимо отобразить сообщения обратной связи, например "Операция выполнена успешно" или "Ошибка".
Для таких сообщений, которые "исчезают после однократного отображения", Flask предоставляет flash-сообщения.flash()Механизм.
Пример
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:
# Сохранить сообщение об ошибке в flash, с категорией "error"
flash("Заголовок не может быть пустым", "error")
return redirect(url_for("create_post"))
# Сохранить сообщение об успехе в flash, с категорией "success"
flash(f"Статья '{title}' успешно опубликована!", "success")
return redirect(url_for("create_post"))
return render_template("create_post.html")
@app.route("/flash-demo")
def flash_demo():
# Получить все flash-сообщения (автоматически очищаются после чтения)
messages = get_flashed_messages(with_categories=True)
return render_template("flash_demo.html", messages=messages)
Отображение flash-сообщений в шаблонах:
Пример
<!DOCTYPE html>
<html>
<head>
<title>Опубликовать статью - 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>Опубликовать статью</h1>
<!-- Получить и отобразить все flash-сообщения -->
{% 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>Заголовок:<input type="text" name="title" style="width:300px;"></p>
<p><input type="submit" value="Опубликовать"></p>
</форма>
</body>
</html>
| Категория | Рекомендуемые сценарии использования |
|---|---|
| "message" (по умолчанию) | Общее уведомление |
| "success" | Операция выполнена успешно |
| "error" | Операция не удалась |
| "warning" | Предупреждающее сообщение |
| "info" | Общая информация |
Flash-сообщения зависят от Session, поэтому необходимо задать секретный ключ.SECRET_KEYТолько тогда его можно использовать.
Вопросы и ответы по Session
Другие расширенияОграничение размера CookieПримечание: Браузеры ограничивают размер одного Cookie примерно 4KB. Не храните большие объёмы данных в Session — он подходит для лёгкой информации, такой как идентификаторы пользователей и настройки, а не для файлов или больших объектов.