HTTP 协议是无状态的:浏览器每次请求,服务器都"不认识你"。但登录后刷新页面,服务器怎么知道"你还是刚才那个用户"?答案:Cookie 里存一个"身份凭证",服务器看到凭证就认出来。
Flask 把这件事封装成 session 对象——你可以像用字典一样存取用户状态,Flask 自动序列化到 Cookie、每次请求自动读取。
💡 关键直觉:session 是"服务器发放的会员卡",Cookie 是"口袋里那张卡"。卡上写的是会员信息(session 数据),每次进门(请求)出示卡片。
Set-Cookie 响应头下发 CookieCookie 请求头)from flask import Flask, session app = Flask(__name__) app.secret_key = '请替换为随机密钥' # 必须配置! @app.route('/login/<username>') def login(username): session['username'] = username # 写入 session session['logged_in'] = True return f"{username} 登录成功" @app.route('/profile') def profile(): username = session.get('username') if not username: return "请先登录", 401 return f"你好,{username}"
关键点:
secret_key:Flask 用它对 session 数据签名(防篡改)。不配置会报错。session['key']=value 存、session.get('key') 取。⚠️ 常见坑:Flask 的 session 默认是"客户端会话"。数据存在 Cookie 里,所以:不能存敏感信息(会被用户看到,只是防篡改不防查看)、有大小限制(Cookie 4KB)、密钥泄露=可伪造 session。生产环境大数据用服务端 session(如 Flask-Session 扩展)。
from flask import Flask, session, redirect, url_for, request app = Flask(__name__) app.secret_key = 'dev-secret-key-change-me' @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') # 实际项目:查数据库验证(第三章 Flask-Login) if username == 'admin' and password == 'secret': session['username'] = username return redirect(url_for('dashboard')) return "用户名或密码错误", 401 return "显示登录表单" @app.route('/dashboard') def dashboard(): if 'username' not in session: return redirect(url_for('login')) return f"欢迎,{session['username']}" @app.route('/logout') def logout(): session.pop('username', None) # 清除用户标识 return redirect(url_for('login'))
登录流程:POST 验证 → 写入 session → 重定向到受保护页面;受保护页面检查 session;登出清除 session。
# 生产环境的安全配置 app.config.update( SECRET_KEY='用 secrets.token_hex(32) 生成', SESSION_COOKIE_HTTPONLY=True, # JS 不能读取 Cookie(防 XSS 窃取) SESSION_COOKIE_SAMESITE='Lax', # 防 CSRF 的基础 # SESSION_COOKIE_SECURE=True, # 仅 HTTPS 传输(生产开启) )
💡 关键直觉:密钥是 session 安全的命根子。用
secrets.token_hex(32)生成随机密钥,存环境变量,绝不硬编码在代码里。
from flask import Flask, session app = Flask(__name__) app.secret_key = 'demo-key' @app.route('/') def counter(): # 每次访问 +1 session['count'] = session.get('count', 0) + 1 return f"这是你第 {session['count']} 次访问" if __name__ == '__main__': app.run(debug=True)
访问刷新几次,观察计数递增——这就是 session 的最直观演示。清浏览器 Cookie 再访问,计数重置。
默认的客户端 session 有大小限制与安全顾虑。生产项目常用 Flask-Session 把 session 存到服务端(Redis/数据库):
from flask import Flask, session from flask_session import Session app = Flask(__name__) app.config.update( SECRET_KEY='secret', SESSION_TYPE='redis', # 存 Redis SESSION_PERMANENT=False, ) Session(app)
何时用服务端 session:session 数据大(超过 Cookie 限制)、需要服务端强制失效(踢人下线)、高安全要求(不想数据暴露在客户端)。
问:session 和 Cookie 什么关系?
session 是"逻辑概念"(用户状态),Cookie 是"实现载体"(客户端存储)。Flask 默认用 Cookie 存 session 数据。
问:session 数据能存多少?
默认存 Cookie 里,受 4KB 限制。大数据用服务端 session(Redis 等)。
问:session 会过期吗?
Flask 默认 session 是"会话级"(关浏览器失效);session.permanent = True + PERMANENT_SESSION_LIFETIME 可设持久化。
问:登录状态在别处改了怎么办?
客户端 session 无法在服务端主动失效(除非换 secret_key 或等服务端方案)。要踢人下线,用服务端 session。
会话解决了"记住用户",但"代码怎么拆开"还没解决。下一节看蓝图(Blueprints)——把单文件应用拆成模块。
理解了 session 的机制后,有几个实战中绕不开的细节值得展开。
第一,session 到底存在哪里。 Flask 默认把 session 数据签名后存进 Cookie(客户端)。服务器用 SECRET_KEY 对数据签名,客户端改不了内容(改了签名就不匹配)。这意味着:session 数据有大小限制(Cookie 约 4KB),不适合存大对象(如整个用户资料),只适合存标识(用户 id、登录标记)。需要存大数据的场景,应该用服务端存储方案(数据库表、Redis),Cookie 里只放一个 session id。
第二,登录状态的完整链路。 一次"记住我"登录的完整流程是:登录成功 → login_user(user, remember=True) → Flask 写两个 Cookie(一个会话 Cookie 存 user_id 签名,一个记住我 Cookie 存长期令牌)→ 后续请求读取会话 Cookie 恢复登录态 → 会话 Cookie 过期后,Flask-Login 用记住我 Cookie 里的令牌自动重新登录。这个机制你不需要自己实现,但理解它有助于排查"为什么登录状态时有时无"——多半是 Cookie 过期时间、HTTPS 配置或令牌失效策略的问题。
第三,登出要彻底。 logout_user() 会清除会话中的用户标识,但不会清除浏览器里其他自定义 Cookie。如果登录状态存储在多个地方(session + 自定义 Cookie + 服务端 token),登出时需要全部清理,否则出现"明明登出了,刷新又变回登录态"的怪现象。
第四,会话过期策略。 默认会话在浏览器关闭后过期(会话 Cookie 不设过期时间)。需要"关闭浏览器后仍保持登录"就设置 PERMANENT_SESSION_LIFETIME 与 remember;需要"强制一段时间后重新登录"就设短一点的过期时间。安全与便利的平衡:后台管理类应用建议短会话+频繁验证,普通用户端可以宽松一些。
第五,多端登录的处理。 同一账号在手机和电脑同时登录,默认 Flask 会话互不影响(各自一套 Cookie)。要实现"一处登出全部下线"(踢人),需要把会话版本号存数据库,每次请求校验——这是进阶话题,本章先知道"默认多端并存"即可。
实战提醒:生产环境务必配置 SECRET_KEY(随机、长、保密),并用 HTTPS(SESSION_COOKIE_SECURE=True)。会话安全是"登录系统"的底线,第四章 4.2 还会系统讲一遍 Web 安全。