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_SECURESESSION_COOKIE_HTTPONLYSESSION_COOKIE_SAMESITE等。Session默认存储在签名Cookie中,数据有4KB大小限制且仅签名未加密,适合存储用户ID等轻量非敏感信息。

相关推荐
郑州光合科技余经理2 小时前
本地生活服务系统:成品模块和定制接口怎么划界
java·前端·人工智能·后端·系统架构·php·ai编程
2603_965148112 小时前
家居百货蓝海:API挖掘高复购率生活小商品
大数据·服务器·人工智能·python·生活
阿童木写作6 小时前
跨境电商图片翻译工具推荐:批量图片翻译+视频字幕翻译+智能抠图
python·macos·音视频·xcode
cui_ruicheng6 小时前
LangChain 应用开发(十四):Agent 上下文与记忆机制
服务器·人工智能·python·langchain
circuitsosk7 小时前
任务规划器的三种范式对比:ReAct、Plan-and-Execute 与 Tree-of-Thought 在真实业务中的取舍
前端·javascript·python·react.js·llm·ai agent
shehuiyuelaiyuehao7 小时前
算法31,前缀和,可被k整除的子数组
数据结构·python·算法
宸津-代码粉碎机7 小时前
AI攻防战升级!基于Spring AI构建Java应用自动免疫安全体系
java·大数据·开发语言·人工智能·python·安全·spring
测试19987 小时前
如何用appium搭建Android自动化测试框架?
自动化测试·软件测试·python·测试工具·职场和发展·appium·测试用例
程序员大雄学编程8 小时前
微积分46. 无穷级数四大核心性质:从理论到实践的全方位解析
python·学习·微积分·学习工具