零基础入门python23:Flask-Login登录、退出与会话
零基础入门python23Flask-Login登录、退出与会话一、上一篇课后练习讲解邮箱大小写测试应先用AliceExample.com注册再用aliceexample.com登录并断言数据库只有一条用户记录。归一化应发生在查询和写入之前。上一篇课后练习完整答案上一篇练习的要求已落实到下面完整文件先运行项目测试再用 curl 对照状态码和数据库持久化结果答案要点注册先规范化邮箱和校验密码再生成带盐哈希唯一约束冲突捕获 IntegrityError 后 rollback 并返回 409。文件app/auth.py完整参考答案文件完整文件app/auth.pyfromflaskimportBlueprint,requestfromsqlalchemy.excimportIntegrityErrorfromwerkzeug.securityimportgenerate_password_hashfrom.extensionsimportdbfrom.modelsimportUser bpBlueprint(auth,__name__,url_prefix/api/auth)bp.post(/register)defregister():datarequest.get_json(silentTrue)or{}emailstr(data.get(email,)).strip().casefold()passwordstr(data.get(password,))ifnotinemailorlen(password)8:return{error:input_invalid},400db.session.add(User(emailemail,password_hashgenerate_password_hash(password)))try:db.session.commit()exceptIntegrityError:db.session.rollback()return{error:email_exists},409return{email:email},201完整参考答案文件本篇对应的交付源码完整文件flask-ledger/app/auth.pyfromflaskimportBlueprint,requestfromflask_loginimportcurrent_user,login_required,login_user,logout_userfrom.extensionsimportdbfrom.modelsimportUser bpBlueprint(auth,__name__,url_prefix/api/auth)bp.post(/register)defregister():datarequest.get_json(silentTrue)or{}emailstr(data.get(email,)).strip().lower()passwordstr(data.get(password,))ifnotinemail:return{message:邮箱格式不正确},400iflen(password)8:return{message:密码至少8位},400ifdb.session.scalar(db.select(User).where(User.emailemail)):return{message:邮箱已注册},409userUser(emailemail)user.set_password(password)db.session.add(user)db.session.commit()return{id:user.id,email:user.email},201bp.post(/login)deflogin():datarequest.get_json(silentTrue)or{}emailstr(data.get(email,)).strip().lower()userdb.session.scalar(db.select(User).where(User.emailemail))ifnotuserornotuser.check_password(str(data.get(password,))):return{message:邮箱或密码错误},401login_user(user)return{id:user.id,email:user.email}bp.post(/logout)login_requireddeflogout():logout_user()return{message:已退出}bp.get(/me)login_requireddefme():return{id:current_user.id,email:current_user.email}验收命令python -m pytest -qDjango 项目使用 python manage.py test。预期测试通过若失败先检查迁移、配置和事务回滚。二、本篇完成什么让注册用户登录并保持会话完成/me查看当前用户和/logout退出。登录状态由 Flask-Login 从 session 恢复受保护接口使用login_required。三、为什么不用客户端传 user_id/me从current_user.id读取身份而不是接受 JSON 中的user_id。客户端提供的 id 只是普通输入不能作为授权依据身份必须来自已经验证的 session。四、验收流程curl-c cookies.txt-X POST http://127.0.0.1:5000/api/auth/login-HContent-Type: application/json-d{\email\:\aliceexample.com\,\password\:\secret123\}curl-b cookies.txt http://127.0.0.1:5000/api/auth/me curl-b cookies.txt-X POST http://127.0.0.1:5000/api/auth/logout curl-b cookies.txt http://127.0.0.1:5000/api/auth/me预期登录和/me为 200退出后/me为 401。测试必须覆盖错误密码、未登录访问和退出后会话失效。课后练习增加会话过期配置并解释开发环境和生产环境的 Cookie 安全属性差异。项目增量Flask-Login 会话边界登录成功后使用安全 cookie 保存会话标识服务器通过 user_loader 从数据库加载用户注销必须清除会话禁用用户不能继续访问。login_manager.user_loaderdefload_user(user_id):returndb.session.get(User,int(user_id))auth_bp.post(/login)deflogin():userUser.query.filter_by(emailrequest.form[email].strip().casefold()).first()ifuserisNoneornotuser.check_password(request.form[password]):abort(401)login_user(user)returnredirect(url_for(ledger.index))验收未登录访问账目返回 401 或重定向登录后只能看到自己的数据课后练习测试 session cookie 和禁用用户。五、会话到底保存了什么Flask-Login 默认在 cookie 中保存一个不可直接信任的用户标识服务端每次请求通过user_loader查询用户。cookie 被篡改时签名校验会失败current_user变成匿名用户因此不能把“是否登录”交给前端传来的user_id。login_manager.user_loaderdefload_user(user_id:str):# 统一从数据库加载找不到用户时返回 None框架会按匿名用户处理。try:returndb.session.get(User,int(user_id))except(TypeError,ValueError):returnNonelogin_manager.unauthorized_handlerdefunauthorized():# API 客户端需要 JSON 和 401而不是浏览器登录页的 302 跳转。return{error:login_required},401登录接口不应区分“邮箱不存在”和“密码错误”否则攻击者可以枚举注册用户。remember会生成更长寿命的 cookie只有在用户明确勾选时才启用。若项目改成前后端分离并使用 JWT仍然需要保留同样的认证边界只是令牌存储位置不同。六、用测试客户端证明 cookie 生效deftest_login_session(client,user):responseclient.post(/api/auth/login,json{email:user.email,password:correct-horse})assertresponse.status_code200meclient.get(/api/auth/me)assertme.status_code200assertme.json[id]user.idclient.post(/api/auth/logout)assertclient.get(/api/auth/me).status_code401测试中必须复用同一个client因为 cookie 存在客户端对象里。出现“明明登录了仍是 401”时检查SECRET_KEY是否在每次创建应用时稳定以及user_loader是否把字符串 id 转成整数如果每次请求都创建新 client会话当然不会保留。七、禁用用户和会话失效在User增加is_active字段后is_authenticated仍然可以为真但is_active应在user_loader中检查。管理员禁用用户后下一次请求应立即失效而不是等 cookie 自然过期login_manager.user_loaderdefload_user(user_id):userdb.session.get(User,int(user_id))returnuserifuseranduser.is_activeelseNone八、上一篇练习讲解与本篇练习上一篇的并发注册测试应使用两个独立 Session本篇练习增加GET /api/auth/me和禁用用户测试要求退出后再次访问返回 401。下一篇会在这个身份基础上实现分类 CRUD并演示越权访问必须返回 404 还是 403。九、Cookie 安全实验在浏览器开发者工具的 Application → Cookies 中确认会话 cookie 具有HttpOnly和SameSiteLax若线上使用 HTTPS再打开Secure。把 cookie 的值改一个字符后重新访问/api/auth/me应得到 401说明签名校验生效。不要把 Flask 的签名 cookie 当作“加密数据库”其中内容仍可能被读取敏感资料应放服务端 Session 或数据库。如果采用前后端分离跨域请求还要正确设置 CORS 的supports_credentials并限制允许的 origin不能写*同时携带 cookie。完成实验后清理浏览器 cookie避免旧会话干扰下一次测试。本篇结束完整模块文件下面是交付项目中真实存在的完整文件 flask-ledger/app/auth.py。它覆盖本篇新增逻辑以及前文已经完成的依赖代码复制单个函数会丢失上下文因此这里提供整份文件。fromflaskimportBlueprint,requestfromflask_loginimportcurrent_user,login_required,login_user,logout_userfrom.extensionsimportdbfrom.modelsimportUser bpBlueprint(auth,__name__,url_prefix/api/auth)bp.post(/register)defregister():datarequest.get_json(silentTrue)or{}emailstr(data.get(email,)).strip().lower()passwordstr(data.get(password,))ifnotinemail:return{message:邮箱格式不正确},400iflen(password)8:return{message:密码至少8位},400ifdb.session.scalar(db.select(User).where(User.emailemail)):return{message:邮箱已注册},409userUser(emailemail)user.set_password(password)db.session.add(user)db.session.commit()return{id:user.id,email:user.email},201bp.post(/login)deflogin():datarequest.get_json(silentTrue)or{}emailstr(data.get(email,)).strip().lower()userdb.session.scalar(db.select(User).where(User.emailemail))ifnotuserornotuser.check_password(str(data.get(password,))):return{message:邮箱或密码错误},401login_user(user)return{id:user.id,email:user.email}bp.post(/logout)login_requireddeflogout():logout_user()return{message:已退出}bp.get(/me)login_requireddefme():return{id:current_user.id,email:current_user.email}

相关新闻

操作教程丨WorkBuddy 接入企业数据MCP流程与应用示例

操作教程丨WorkBuddy 接入企业数据MCP流程与应用示例

随着 AI Agent 应用的发展,越来越多智能体开始从简单的信息问答,向任务执行和数据分析方向发展。但在实际企业场景中,模型自身掌握的信息往往无法满足实时查询需求,例如企业尽调、供应商审核、投资分析等任务,都需要结…

2026/8/26 18:56:35 阅读更多 →
震惊!芯片推拉力测试机供应商,你必须知道这5家!

震惊!芯片推拉力测试机供应商,你必须知道这5家!

当一颗芯片从晶圆上切割、键合、封装,到最终成为能够驱动智能设备的“心脏”,每一个环节都隐藏着对可靠性的极致要求。而在半导体制造与封装的庞大版图中,芯片推拉力测试机堪称衡量焊接强度与键合质量的“守门员”,是确保芯片长期…

2026/8/27 19:26:42 阅读更多 →
告别手动录题|免费刷题工具,一键导入即刷

告别手动录题|免费刷题工具,一键导入即刷

📚 告别手动录题|免费刷题工具,一键导入即刷备考刷题想要高效提分,一套完整、整洁、规范的专属题库至关重要。但绝大多数考生都会遇到相同难题:网上题库格式杂乱、排版错乱、无法直接使用,手动录入耗时费力…

2026/8/27 19:26:14 阅读更多 →

最新新闻

Python 机器学习库 Top 10,你值得拥有!

Python 机器学习库 Top 10,你值得拥有!

随着人工智能技术发展且普及开来, 它超越了好多其他编程语言, 变成了机器学习领域里极热门且极常用的编程语言当中的一个。致使它在众多开发者里这般受追捧存在好多缘由, 其中一个便是它有着大量跟机器学习相关的开源框架以及工具库。依据它的数据表明, 45%的科技公司都趋向于把…

2026/8/27 21:11:25 阅读更多 →
MathorCup大数据建模实战:时序信号处理与轻量化故障预测

MathorCup大数据建模实战:时序信号处理与轻量化故障预测

1. 这不是一份“交差代码”,而是一套可复用的大数据建模工作流MathorCup高校数学建模挑战赛的B题,从来就不是考你能不能把几行Python跑通。2023年第四届大赛B题——大数据竞赛题,核心落在“大数据”三个字上,但真正拉开差距的&…

2026/8/27 21:11:25 阅读更多 →
D5渲染器+SketchUp室外建筑渲染全流程实战指南

D5渲染器+SketchUp室外建筑渲染全流程实战指南

SketchUp 建模效率高,但直接出图总差一口气;D5 渲染器实时反馈快、材质表现好,但很多人卡在“模型同步不成功”和“室外场景调不出质感”这两步。这次我们直接把 D5 渲染器 SketchUp 室外建筑渲染这条完整链路走一遍:从软件安装、…

2026/8/27 21:11:25 阅读更多 →
Python 基础知识:什么是 Python 中的上下文管理器(Context Manager)?

Python 基础知识:什么是 Python 中的上下文管理器(Context Manager)?

处于某种情境之中时, 有一种被称作上下文管理器的对象, 它专门用来对资源予以管理, 它明确规定了在正要进入以及刚刚退出特定代码板块之际务必要执行的相关操作。该种上下文管理器常常被运用在保障资源能够得以正确地进行分配以及释放的进程当中, 就好比开启以及关闭文件, 建立…

2026/8/27 21:11:25 阅读更多 →
零基础学Python,我在成都编程云教室的一个多月的真实经历

零基础学Python,我在成都编程云教室的一个多月的真实经历

一、写在前面:为什么我一个零基础的人敢去学作出决定报名之前, 我实实在在纠结了好长段时间, 身为一个压根儿没接触过编程之人, 瞅见满屏幕到处都是英文和符号就心生畏惧, 老是觉得自己学不咋样, 然而身旁越来越多的朋友凭借它找出了工作、得以接上兼职项目了, 再加…

2026/8/27 21:11:25 阅读更多 →
Java开发中的代码复用:从继承到组合的实践思考

Java开发中的代码复用:从继承到组合的实践思考

继承曾经是Java世界最引以为傲的复用武器,如今却成了无数项目腐化的温床。当你写下extends关键字时,你不仅继承了父类的字段和方法,还继承了它的全部秘密——私有状态可以通过受保护方法间接影响、子类方法的调用时机被父类构造器悄悄劫持、未…

2026/8/27 21:10:24 阅读更多 →

日新闻

Go语言构建企业级AI服务网关:统一管理英伟达等AI接口调用

Go语言构建企业级AI服务网关:统一管理英伟达等AI接口调用

1. 项目概述:从零构建一个企业级的AI服务网关 最近在帮一个做内容审核的团队做技术架构升级,他们原来的业务里,每天有几十万张图片和短视频需要过审,最初是接了几个开源的AI模型自己部署,但效果和性能一直不太稳定。后…

2026/8/27 0:00:51 阅读更多 →
网盘直链下载助手5分钟解析八大网盘真实地址

网盘直链下载助手5分钟解析八大网盘真实地址

网盘直链下载助手5分钟解析八大网盘真实地址 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅雷云盘 / 夸…

2026/8/27 1:06:27 阅读更多 →
从零点亮 ESP32:Arduino ESP32 开发环境搭建与首次烧录完整指南

从零点亮 ESP32:Arduino ESP32 开发环境搭建与首次烧录完整指南

从零点亮 ESP32:Arduino ESP32 开发环境搭建与首次烧录完整指南 【免费下载链接】arduino-esp32 Arduino core for the ESP32 family of SoCs 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 Arduino ESP32 是乐鑫官方的 ESP32 系列 Ardui…

2026/8/27 1:06:27 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/26 14:45:33 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/26 17:46:43 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 14:46:37 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/27 17:46:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/26 17:46:39 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/27 20:00:17 阅读更多 →