Flask入门教程(二十六):Session API——用户会话状态管理

1. session代理对象

session是一个代理,指向当前请求的SessionMixin实例。只在请求上下文中可用。

属性/方法 说明
session[key] = value 设置session值
session.get(key, default) 安全获取session值,键不存在时返回default
session.pop(key, default) 移除并返回指定键的值
session.clear() 清空所有session数据
"key" in session 检查键是否存在
session.permanent 设为True时,Session在浏览器关闭后仍保持
session.modified 修改嵌套可变对象时需手动设为True
session.accessed session被访问时为True
session.new session是否为新创建

2. 基本操作

复制代码
from flask import Flask, session, redirect, url_for, request

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

# 设置值
@app.route("/set")
def set_session():
    session["username"] = "runoob"
    session["user_id"] = 1001
    session["preferences"] = {"theme": "dark", "lang": "zh"}
    return "Session已设置"

# 读取值
@app.route("/get")
def get_session():
    username = session.get("username", "访客")  # 安全获取
    # 或直接访问(可能抛出KeyError)
    # username = session["username"]
    return f"用户名: {username}"

# 检查是否存在
@app.route("/check")
def check_session():
    if "username" in session:
        return f"用户已登录: {session['username']}"
    return "未登录"

# 删除特定键
@app.route("/remove")
def remove_session():
    session.pop("username", None)
    return "username已移除"

# 清空全部
@app.route("/clear")
def clear_session():
    session.clear()
    return "Session已清空"

3. 永久Session

默认情况下,Session在浏览器关闭后失效 (会话级别)。通过设置session.permanent = True可使其在浏览器关闭后仍然有效,有效期由PERMANENT_SESSION_LIFETIME配置控制。

复制代码
from datetime import timedelta

# 配置:设置永久session有效期为7天
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=7)

@app.route("/login", methods=["POST"])
def login():
    session["username"] = request.form.get("username")
    # 标记为永久session
    session.permanent = True
    return redirect(url_for("index"))

4. 重要:modified标记

当修改session中嵌套的可变对象 (如列表、字典)时,Flask无法自动检测到修改 。必须手动设置session.modified = True,否则修改不会保存到Cookie中。

复制代码
@app.route("/append")
def append_item():
    # ❌ 错误:直接修改列表,Flask检测不到
    if "items" not in session:
        session["items"] = []
    session["items"].append("new_item")
    # 修改不会保存!

    # ✅ 正确:手动标记modified
    if "items" not in session:
        session["items"] = []
    session["items"].append("new_item")
    session.modified = True  # 必须手动标记!
    return f"Items: {session['items']}"

# 替代方案:重新赋值(自动触发modified)
@app.route("/set-list")
def set_list():
    items = session.get("items", [])
    items.append("new_item")
    session["items"] = items  # 重新赋值,Flask能检测到
    return f"Items: {session['items']}"
操作类型 是否需要手动modified=True
session["key"] = value(赋值) ❌ 否(自动检测)
session.pop("key") ❌ 否(自动检测)
session["list"].append(x)(修改嵌套对象) ✅ 是(必须手动)
session["dict"]["key"] = value(修改嵌套字典) ✅ 是(必须手动)

5. Session相关配置项

配置键 默认值 说明
SECRET_KEY None 签名Session的密钥,必须设置才能使用Session
SESSION_COOKIE_NAME "session" Session Cookie的名称
SESSION_COOKIE_DOMAIN None Cookie的Domain属性
SESSION_COOKIE_PATH None Cookie的Path属性
SESSION_COOKIE_HTTPONLY True 禁止JavaScript访问Session Cookie
SESSION_COOKIE_SECURE False 为True时仅通过HTTPS发送
SESSION_COOKIE_SAMESITE None "Strict"、"Lax"或None
PERMANENT_SESSION_LIFETIME timedelta(days=31) 永久Session的有效期
SESSION_REFRESH_EACH_REQUEST True 每次请求都刷新Session Cookie的有效期

生产环境Session配置推荐

复制代码
# app.py
import os
from datetime import timedelta

app.config.update(
    SECRET_KEY=os.environ.get("SECRET_KEY"),  # 从环境变量读取
    SESSION_COOKIE_SECURE=True,                # 仅HTTPS传输
    SESSION_COOKIE_HTTPONLY=True,              # 禁止JavaScript访问
    SESSION_COOKIE_SAMESITE="Lax",             # 防范CSRF
    PERMANENT_SESSION_LIFETIME=timedelta(days=7),  # 7天有效期
    SESSION_REFRESH_EACH_REQUEST=False,        # 不自动刷新,减少Cookie写入
)

6. 完整代码示例

复制代码
from flask import Flask, session, redirect, url_for, request
from datetime import timedelta

app = Flask(__name__)
app.secret_key = "dev-secret-key"
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=7)

@app.route("/")
def index():
    username = session.get("username", "访客")
    items = session.get("items", [])
    return f"""
    <h1>欢迎, {username}!</h1>
    <p>购物车: {items}</p>
    <p><a href="/login">登录</a> | <a href="/add-item">添加商品</a> | <a href="/logout">退出</a></p>
    """

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        session["username"] = request.form.get("username", "用户")
        session["items"] = []
        session.permanent = True
        return redirect(url_for("index"))
    return '<form method="post"><input name="username"><input type="submit"></form>'

@app.route("/add-item")
def add_item():
    if "items" not in session:
        session["items"] = []
    session["items"].append(f"商品{len(session['items']) + 1}")
    session.modified = True  # 修改嵌套列表,必须手动标记!
    return redirect(url_for("index"))

@app.route("/logout")
def logout():
    session.clear()
    return redirect(url_for("index"))

7. Session API速查表

操作 代码
设置值 session["key"] = "value"
读取值(安全) session.get("key", "default")
读取值(直接) session["key"](键不存在抛KeyError)
检查键是否存在 "key" in session
删除键 session.pop("key", None)
清空所有 session.clear()
设置永久 session.permanent = True
标记已修改 session.modified = True
获取所有键 list(session.keys())

8. 安全注意事项

⚠️ 风险 ✅ 防护措施
密钥泄露导致Session伪造 SECRET_KEY从环境变量读取,不提交到Git
Session被窃取(中间人攻击) 生产环境启用SESSION_COOKIE_SECURE=True
XSS窃取Session 使用SESSION_COOKIE_HTTPONLY=True
CSRF攻击 配合SESSION_COOKIE_SAMESITE="Lax"或使用Flask-WTF
复制代码
# 生产环境密钥管理最佳实践
import os
import secrets

# 开发环境:自动生成,但提交到Git时忽略
if os.environ.get("FLASK_ENV") == "development":
    app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY", secrets.token_hex(32))
else:
    # 生产环境:必须从环境变量读取
    app.config["SECRET_KEY"] = os.environ["SECRET_KEY"]

小结

本章全面讲解了Flask Session的完整API。session代理对象支持字典式操作(session[key]、session.get()、session.pop()、session.clear()、in检查);永久Session通过session.permanent = True启用,有效期由PERMANENT_SESSION_LIFETIME控制;修改嵌套可变对象(如列表append、字典嵌套赋值)时必须手动设置session.modified = True,否则修改不会保存;相关配置项包括SECRET_KEY(必须设置)、SESSION_COOKIE_SECURE、SESSION_COOKIE_HTTPONLY、SESSION_COOKIE_SAMESITE等。Session默认存储在签名Cookie中,数据有4KB大小限制且仅签名未加密,适合存储用户ID等轻量非敏感信息。

相关推荐
Smoothcloud润云15 分钟前
PyTorch推理服务模型热切换与失败回滚实战:降低版本更新中断
服务器·人工智能·pytorch·python·深度学习·gpu
jsjzsl228 分钟前
递归自改进系统(RSI)的本质是自发对称破缺:智能爆炸有界—— AI研发切记盲目投入
人工智能·python·算法
2601_9548118244 分钟前
机器视觉教学套件选型指南:五维技术参数对比与课程体系评估
python·数码相机
凤山老林1 小时前
Spring Boot 集成 Sa-Token 实现高可用权限认证:登录鉴权、动态路由权限与接口防重放实战
spring boot·后端·sa-token·bootstrap
小马不起床1 小时前
零基础玩转 FastAPI_05:后端课程模块
python·fastapi
小王2042 小时前
Day 41:模型注意力机制 — SE / CBAM / ECA
python·深度学习·机器学习
Bazingga2 小时前
一次推理的完整旅程:ReAct推理深度解析
后端
171320330计算机毕设编程2 小时前
计算机毕业设计 基于YOLO改进算法的车辆特征识别系统设计与实现--lw
java·大数据·python·sql·算法
Web极客码2 小时前
Python Ollama 本地 Agent 入门与订单查询实践
开发语言·jvm·python
姜鱼问生2 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构