登录、会话与权限
认证回答“你是谁”,授权回答“你能做什么”。按钮是否显示不能代替服务端权限检查。
- 所有敏感操作都有服务端身份与权限依据。
- 密码哈希、会话、Cookie 和令牌
- 保护一个管理接口,分别验证匿名、普通用户和管理员三种结果。
- 完成 6.4「Redis 与缓存:什么时候才需要」
FOUNDATION
必须理解
认证回答“你是谁”,授权回答“你能做什么”。按钮是否显示不能代替服务端权限检查。
认证确认“你是谁”,会话让后续请求记住身份,授权决定“你能做什么”。登录页只是入口,真正安全边界必须在每一次服务端数据操作中执行。
进入办公楼先用证件确认身份,这是认证;领取临时门卡维持会话;不同楼层门禁决定授权。看到某扇门不代表有权打开。
用户登录后获得安全会话;查询、更新或删除任务时,服务端都用会话中的 userId 限制 ownerId,绝不相信前端传来的“这是我的任务”。
密码哈希、会话、Cookie 和令牌
认证是在确认“你到底是谁”,可以用密码、第三方账号或登录链接完成。密码不能明文保存,也别自己发明加密方法,成熟认证库已经处理了大量容易踩坑的细节。
基础概念
认证确认访问者是谁,会话让后续请求持续关联这个身份。密码应经过专用密码哈希算法处理,Cookie 或令牌只承载会话凭证,不应直接保存明文密码。
进一步理解
注册时保存带盐密码哈希;登录时用同一算法验证。成功后服务端建立会话,浏览器通过安全 Cookie 在后续请求中携带会话标识。
HttpOnly 限制脚本读取 Cookie,Secure 要求 HTTPS 传输,SameSite 降低部分跨站请求风险。它们各防一类问题,不能互相替代。
用户登录任务应用后获得会话 Cookie;每次读取任务,服务端从会话取得 userId,而不是要求前端重复发送密码。
哈希不是可逆加密,会话令牌也不等于用户身份本身;服务器仍需验证令牌有效、未过期且未撤销。
这一小节记住:密码只用于证明身份,会话用受控凭证延续身份。
角色、资源所有权和最小权限
用户登录一次后,网站需要在后续请求中认出他,这就是会话。安全 Cookie 常用来携带会话信息,HttpOnly、Secure 和 SameSite 分别挡住一部分常见风险。
基础概念
授权决定已认证身份可以执行哪些操作。角色描述一类权限,资源所有权限制具体记录,最小权限原则只授予完成当前任务所需能力。
进一步理解
管理员角色可以管理全局配置,普通用户只能操作自己的任务。即使两人调用同一路由,查询条件和业务规则也必须根据身份缩小范围。
权限检查应发生在服务端每个敏感操作上,并尽量靠近数据访问。隐藏按钮只能改善界面,无法阻止自制 HTTP 请求。
更新任务时查询条件同时包含 taskId 与会话 userId;普通用户即使猜到他人 id,也更新不到记录。
认证成功不代表拥有所有权限,角色也不能替代资源归属;“已登录”只解决你是谁,没有回答你能操作哪条数据。
这一小节记住:每次敏感操作都用服务端身份回答:这个人能否对这条资源做这件事?
登录、退出、过期和找回流程
授权回答的是“这个人能不能做这件事”。按钮藏起来只影响页面,真正的判断必须在服务端做,因为别人完全可以绕过页面直接请求 API。
基础概念
完整身份流程包括登录、退出、会话过期和账户找回。每条路径都在改变谁能继续使用账户,因此必须设计安全反馈、撤销和异常状态。
进一步理解
退出应让当前会话失效;过期后引导重新认证并尽量保存未提交工作;找回流程使用短期、一次性令牌并避免泄露账户是否存在。
修改密码、发现异常或管理员封禁时,可能需要撤销其他会话。重要操作可要求近期重新认证,而不是无限信任旧会话。
用户找回密码后,重置链接立即失效,旧会话按策略撤销;返回登录页时不暴露该邮箱是否注册。
“记住我”不是永不过期;延长会话会增加被盗后的风险,需要设备管理、撤销与重新认证配合。
这一小节记住:身份系统要覆盖进入、持续、离开和恢复,而不只是一个登录表单。
AI COLLABORATION
AI 如何参与
让 AI 对每个写操作说明服务端如何确认身份和权限,并列出越权测试。
推荐协作顺序
- 1
先让 AI 画出登录、会话和授权三段流程,不生成加密算法。
- 2
选择成熟认证库后,只参考当前版本的官方接入方式。
- 3
用两个测试账户让 AI 帮你设计越权用例,再亲自验证服务端结果。
请为 Next.js + PostgreSQL 的任务应用设计最小认证与授权流程。使用成熟认证库,不自行发明加密。画出注册/登录、创建会话、读取当前用户任务、删除任务四条流程,并标出每一步的信任边界和失败状态。
服务端从可信会话取得 userId,每次数据查询都带 ownerId;错误区分未登录与无权限,但不泄露其他用户资源是否存在。
人工检查清单
- 确认密码不进入日志或客户端包,Cookie 属性安全,授权不是只在前端执行。
- 要求 AI 为每个读写接口标出身份来源、授权规则和越权测试。
- 用匿名、普通用户、资源所有者和管理员四种身份实际请求,确认服务端结果而非按钮可见性。
COMMON TRAPS
常见误区
错误不是需要隐藏的失败,而是帮助你看清系统边界的证据。下面三类问题在 AI 辅助学习中最常出现。
登录成功就以为权限没问题
- 你会看到
- 用户能进入页面,也能通过改 URL 访问别人的任务。
- 为什么发生
- 明文或快速普通哈希无法抵抗数据库泄露后的离线猜测;隐藏入口又无法阻止直接构造请求。
- 怎样纠正
- 每次服务端读写都按当前会话和资源归属重新授权。
自己实现密码和令牌
- 你会看到
- 用普通哈希或自定义字符串拼出会话,留下严重风险。
- 为什么发生
- 信任请求体中的 userId 或 role 等于允许调用者自己声明身份和权限。
- 怎样纠正
- 使用成熟认证库和专用密码哈希,不发明安全协议。
只在前端隐藏按钮
- 你会看到
- 页面看不到删除按钮,但直接调用 API 仍能删除。
- 为什么发生
- 只实现登录成功路径,会遗留无法撤销的会话、可复用重置链接和过期后的糟糕恢复体验。
- 怎样纠正
- 前端控制展示,服务端控制真正权限,两处职责不能互换。
HANDS-ON
动手任务
保护一个管理接口,分别验证匿名、普通用户和管理员三种结果。
- 完成 6.4「Redis 与缓存:什么时候才需要」
跟着做
- 01
画出认证、会话、授权三者关系。
- 02
选择适配 Next.js 的成熟认证方案并阅读官方指南。
- 03
实现登录和退出,检查 Cookie 的安全属性。
- 04
把任务查询改为按当前 userId 过滤。
- 05
用两个测试账户尝试访问彼此任务并确认被拒绝。
所有敏感操作都有服务端身份与权限依据。
设计“忘记密码”流程,标出令牌有效期、一次性使用和避免暴露账户存在性的要求。
离开本课前,自问四件事
- 认证、会话与授权分别回答什么问题?
- 密码哈希、Cookie 属性和会话撤销各自防什么风险?
- 为什么隐藏管理按钮不能作为权限控制?
- 登录、退出、过期和找回流程分别需要哪些服务端保证?
确认完成后,会同步更新学习中心的课程学习进度。