跳转到内容

Module 12: 认证与授权

📖 深度参考手册 — 本模块属于理论参考,非主线必读。 主线学习路径见 README.md。 当你在项目实战中遇到相关问题时,回来查阅。

系统设计中,“谁能访问什么”是每个生产系统的第一道门。这个模块覆盖从用户登录到权限控制的完整链路。


定义认证(Authentication) 是验证”你是谁”的过程——用户提供凭证(密码、指纹、手机验证码),系统确认其身份。授权(Authorization) 是在认证之后,决定”你能做什么”的过程——系统根据用户的身份和角色,判断其是否有权限执行某个操作。两者经常被混淆,但职责完全不同:认证回答的是身份问题,授权回答的是权限问题。一个常见的类比:认证是门卫检查你的工牌确认你是公司员工,授权是确认你的工牌能刷开哪些楼层的门禁。

为什么重要:混淆认证和授权会导致严重的安全漏洞。常见错误包括:只做了认证没做授权(登录了就能访问所有资源)、把授权逻辑放在前端(用户可以绕过)、或者在API层面遗漏权限检查。在系统设计中,认证和授权是两个独立的关注点,应该分别设计、分别实现。

案例Hotel Reservation — 用户输入邮箱和密码登录系统,这是认证;登录后,普通旅客只能搜索和预订房间,酒店管理员可以修改房价和房态,平台管理员可以查看所有酒店的数据——这些都是授权。如果只做认证不做授权,任何登录用户都能修改房价,这显然是灾难性的。

先想一想 🤔 Chat System 中,哪些操作属于认证范畴,哪些属于授权范畴?

点击查看解析

认证范畴

  • 用户登录(账号密码/OAuth/手机验证码)
  • WebSocket 连接时验证用户身份(携带 token)
  • 消息发送时验证发送者身份

授权范畴

  • 用户只能查看自己参与的聊天(不能偷看别人的私聊)
  • 群主可以踢人、设置管理员,普通成员不行
  • 管理员可以删除违规消息,普通用户不行
  • 只有群成员可以在群内发送消息

关键点:WebSocket 连接建立时做认证,每条消息的操作权限是授权。两者缺一不可。


定义Session 模式:用户登录后,服务端生成一个唯一的 Session ID,将用户信息存储在服务器内存或 Redis 中,然后通过 Set-Cookie 将 Session ID 发给客户端。后续请求客户端自动携带 Cookie,服务端根据 Session ID 查询用户信息。JWT(JSON Web Token)模式:用户登录后,服务端用密钥签发一个包含用户信息的 Token,直接返回给客户端。后续请求客户端在 Authorization 头中携带 JWT,服务端无需查询存储,直接验证签名即可确认用户身份。

两者的核心区别在于状态存储的位置:Session 是服务端有状态(状态存在服务器),JWT 是服务端无状态(状态存在 Token 里)。

为什么重要:选择哪种方案直接影响系统架构:

维度SessionJWT
状态服务端有状态服务端无状态
存储需要 Redis/内存无需服务端存储
扩展性多节点需共享 Session 存储任意节点都能验证
吊销删除 Session 即可需要黑名单机制
大小Cookie 只有 Session ID(很小)JWT 包含完整信息(较大)
跨域Cookie 有同源限制Token 放 Header 无限制

案例Chat System — 假设聊天系统有 10 台 WebSocket 服务器做负载均衡。如果用 Session:用户连接到服务器 A 创建了 Session,下次被分配到服务器 B 就找不到 Session 了,必须引入 Redis 集中存储所有 Session。如果用 JWT:每台服务器都持有相同的签名密钥,用户连接到任意一台都能独立验证 Token,天然适合分布式架构。这就是为什么大多数现代分布式系统倾向于 JWT。

先想一想 🤔 如果一个用户的 JWT 被盗了(比如 XSS 攻击),用 Session 方案和 JWT 方案分别该怎么处理?

点击查看解析

Session 方案

  • 直接在 Redis 中删除该用户的 Session,立即生效
  • 被盗的 Session ID 瞬间失效,攻击者无法继续使用
  • 处理速度:秒级

JWT 方案

  • JWT 一旦签发,在过期之前都是有效的——服务端无法直接”删除”它
  • 需要维护一个 Token 黑名单(存 Redis),每次验证 JWT 时额外检查黑名单
  • 或者更换签名密钥(但这会导致所有用户的 JWT 全部失效)
  • 或者缩短 JWT 过期时间(如 15 分钟),配合 Refresh Token 机制

这是 JWT 最大的缺点:吊销困难。如果你的系统对安全吊销有强需求(如银行系统),Session 可能更合适。


定义:JWT 由三部分组成,用 . 分隔:Header.Payload.Signature

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMjM0LCJyb2xlIjoiYWRtaW4iLCJleHAiOjE3MDAwMDAwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • Header:声明签名算法(如 HS256、RS256)和 Token 类型
  • Payload:存放用户信息(user_id、role)和元数据(exp 过期时间、iat 签发时间)。注意:Payload 是 Base64 编码而非加密,任何人都能解码读取内容
  • Signature:用密钥对 Header + Payload 进行签名,防止篡改。服务端验证时重新计算签名,与 Token 中的签名对比

常见的 JWT 安全陷阱

  1. 不要在 Payload 中存密码等敏感信息——Base64 不是加密,前端打开控制台就能解码
  2. 必须设置过期时间(exp)——永不过期的 JWT 等于永不过期的密码
  3. 使用 Access Token + Refresh Token 双令牌机制——Access Token 短期(15-30 分钟),Refresh Token 长期(7-30 天),Access Token 过期后用 Refresh Token 换新

为什么重要:JWT 是现代 Web 系统最常用的认证机制。理解其内部结构才能避免安全漏洞:曾有开发者将算法设为 none 导致任何人可以伪造 Token;也有开发者把数据库密码写在 Payload 里被攻击者直接 Base64 解码获取。

案例:以 Hotel Reservation 为例,一个实际的 JWT Payload 可能长这样:

{
"user_id": 1234,
"email": "[email protected]",
"role": "hotel_admin",
"hotel_id": 56,
"exp": 1700000000,
"iat": 1699998200
}

服务端收到请求时:(1) 验证签名确认 Token 没被篡改 → (2) 检查 exp 确认没过期 → (3) 读取 role 和 hotel_id 做授权判断(hotel_admin 只能管理自己的酒店)。整个过程不需要查询数据库。

先想一想 🤔 为什么 Access Token 要设计得这么短(15 分钟),而不是直接设一个长过期时间?

点击查看解析

核心原因:缩小安全窗口期

如果 Access Token 有效期是 7 天,一旦被盗,攻击者可以用 7 天。如果只有 15 分钟,攻击者最多用 15 分钟。

双令牌机制的安全设计

  • Access Token(15分钟):每次 API 请求都携带,暴露面大,所以设短
  • Refresh Token(30天):只在刷新时发送一次,暴露面小,所以可以设长
  • Refresh Token 存储在 HttpOnly Cookie 中,JavaScript 无法读取,比 Access Token 更安全
  • 如果检测到异常(如 Refresh Token 被使用两次),可以立即吊销该 Refresh Token

这是一个安全性和用户体验之间的平衡:用户不需要每 15 分钟重新登录(Refresh Token 自动续期),但安全窗口被控制在 15 分钟以内。


定义:OAuth 2.0 是一个授权框架(不是认证协议),允许用户在不暴露密码的情况下,授权第三方应用访问其在其他平台上的资源。它定义了四种授权模式:

  1. 授权码模式(Authorization Code):最安全、最常用。用于有后端的 Web 应用
  2. 隐式模式(Implicit):已不推荐,曾用于纯前端应用
  3. 客户端凭证模式(Client Credentials):服务间通信,没有用户参与
  4. 密码模式(Resource Owner Password):不推荐,用户直接把密码给第三方

授权码模式的完整流程

用户 → 点击"用 GitHub 登录"
→ 浏览器跳转到 GitHub 授权页面
→ 用户在 GitHub 上点击"授权"
→ GitHub 重定向回你的网站,URL 带一个临时 code
→ 你的后端用 code + client_secret 向 GitHub 换取 access_token
→ 你的后端用 access_token 调用 GitHub API 获取用户信息
→ 你的后端为该用户创建账号/登录,签发自己的 JWT

为什么重要:OAuth 2.0 是现代互联网的基石。几乎所有”使用 XX 登录”的功能都基于它。理解 OAuth 不仅是面试常考点,更是理解第三方集成、开放平台、API 授权的基础。关键区别:code 走后端通道换 token(安全),而不是直接在前端暴露 token(不安全,这就是隐式模式被废弃的原因)。

案例YouTube — 当你在某个视频编辑应用中点击”使用 Google 账号登录”时,背后就是 OAuth 2.0 授权码模式。视频编辑应用不需要知道你的 Google 密码,它只需要 Google 告诉它”这个人确实是 Google 用户 XXX”。而当这个应用要读取你的 YouTube 视频列表时,它还需要你额外授权”允许访问 YouTube 数据”——这才是 OAuth 的核心:用户自主控制授权哪些资源给哪些应用

先想一想 🤔 为什么授权码模式要分两步(先拿 code,再换 token),而不是 GitHub 直接返回 token?

点击查看解析

安全原因:code 和 token 走不同的通道

  1. code 走前端通道(浏览器重定向):URL 会出现在浏览器地址栏、浏览器历史记录、服务器日志中,容易泄露
  2. token 走后端通道(服务器到服务器):后端用 code + client_secret 直接调用 GitHub API,不经过浏览器,不会泄露

如果直接在重定向 URL 里返回 token(隐式模式):

  • token 出现在浏览器地址栏 → 被浏览器插件截获
  • token 出现在 Referer 头 → 被第三方网站获取
  • token 出现在浏览器历史 → 被共用电脑的人获取

code 即使泄露也没关系——它是一次性的,且必须配合 client_secret 才能换 token,而 client_secret 只存在后端服务器上。

这就是”授权码模式”比”隐式模式”安全的根本原因,也是隐式模式被 OAuth 2.1 正式废弃的原因。


定义SSO(Single Sign-On) 是一种认证机制,允许用户一次登录,即可访问多个相互信任的系统,无需在每个系统中重复登录。SSO 的核心是一个集中式认证服务(Identity Provider, IdP),所有子系统都信任这个 IdP。

主流实现方式:

  • SAML 2.0:企业级标准,基于 XML,协议较重。常见于传统企业 SSO(如 Okta、AD FS)
  • OIDC(OpenID Connect):基于 OAuth 2.0 之上的认证层,用 JSON 格式,更轻量。返回 ID Token(JWT 格式)证明用户身份。现代应用首选

两者对比:SAML 像企业公文(XML、签名、加密,一套完整但冗长),OIDC 像现代即时通讯(JSON、JWT、简洁高效)。

为什么重要:随着企业系统越来越多(邮箱、OA、CRM、代码仓库、项目管理…),如果每个系统都要单独登录,用户体验极差,且密码管理是安全隐患。SSO 不仅提升了用户体验,还集中了认证逻辑,方便统一管理账号生命周期(员工离职时一处禁用,所有系统即刻断开)。

案例Google 生态系统 — 你登录了 Gmail 之后,打开 YouTube 不需要再登录,打开 Google Drive 也不需要登录。背后就是 Google 的 SSO 系统:Google Accounts 作为 IdP,Gmail、YouTube、Drive、Maps 等所有 Google 服务都是信任方。同样,如果我们的 11 个系统案例(URL Shortener、YouTube、Google Drive、Google Maps)都属于同一个公司,就应该用 SSO 让用户一次登录、处处通行。

先想一想 🤔 如果我们要为 Hotel Reservation 接入企业客户的 SSO(比如某大公司员工用公司账号登录预订差旅酒店),应该选 SAML 还是 OIDC?

点击查看解析

取决于企业客户用什么 IdP,但通常两者都要支持:

  • 大型传统企业(银行、政府、500强):通常用 AD FS、Okta,首选 SAML。这些企业的 IT 部门习惯 SAML 配置流程
  • 科技公司和初创企业:倾向 OIDC,因为更现代、集成更简单

实际做法

  1. 如果是 SaaS 平台(服务多个企业客户),通常同时支持 SAML 和 OIDC
  2. 使用 Auth0 或 WorkOS 这类服务,它们封装了 SAML/OIDC 的复杂性,让你一次集成即可支持两种协议
  3. 企业客户在管理后台配置自己的 IdP 连接信息

关键点:这不是技术选型问题,而是客户兼容性问题。企业 SSO 场景中,你的客户决定了你要支持什么。


定义RBAC(Role-Based Access Control) 是最经典的权限模型,核心思想是用户不直接拥有权限,而是通过角色间接获得权限。三层模型:用户(User)→ 角色(Role)→ 权限(Permission)。

数据模型设计:

users 表 : id, email, name
roles 表 : id, name (如 guest, hotel_admin, platform_admin)
permissions 表 : id, resource, action (如 room:read, room:update, price:update)
user_roles 表 : user_id, role_id (多对多关联)
role_permissions: role_id, permission_id (多对多关联)

权限检查的流程:用户请求”修改房价” → 查 user_roles 得到角色 hotel_admin → 查 role_permissions 得到该角色有 price:update 权限 → 允许操作。

为什么重要:RBAC 的优势在于管理效率。如果有 1000 个酒店管理员,你不需要为每个人单独分配 20 个权限——只需要把他们都分配到 hotel_admin 角色,角色上配好权限即可。新增权限时,修改角色的权限即可影响所有该角色的用户。这比直接给每个用户分配权限(ACL 模式)高效得多。

案例Hotel Reservation 的 RBAC 设计:

角色定义:
├── guest(旅客)
│ ├── room:search - 搜索房间
│ ├── room:read - 查看房间详情
│ ├── booking:create - 创建预订
│ ├── booking:read - 查看自己的预订
│ └── booking:cancel - 取消自己的预订
├── hotel_admin(酒店管理员)
│ ├── room:* - 房间的所有操作(增删改查)
│ ├── price:* - 价格的所有操作
│ ├── booking:read - 查看本酒店的所有预订
│ └── booking:update - 修改预订状态(确认/拒绝)
└── platform_admin(平台管理员)
└── *:* - 所有资源的所有操作

关键细节:hotel_admin 的 booking:read 和 guest 的 booking:read 虽然权限名相同,但数据范围不同——guest 只能看自己的预订,hotel_admin 能看本酒店所有预订。这种数据级别的权限控制需要在 RBAC 之上额外实现。

先想一想 🤔 Gaming Leaderboard 需要哪些角色和权限?

点击查看解析

角色设计

  1. player(玩家)
    • score:submit — 提交自己的分数
    • leaderboard:read — 查看排行榜
    • profile:read — 查看其他玩家主页
    • profile:update_self — 修改自己的昵称/头像
  2. game_admin(游戏管理员)
    • score:* — 管理所有分数(包括删除作弊分数)
    • leaderboard:* — 管理排行榜(重置赛季、配置规则)
    • player:ban — 封禁作弊玩家
    • player:read — 查看玩家详细数据
  3. platform_admin(平台管理员)
    • *:* — 全部权限
    • 包括管理 game_admin 账号、配置系统参数

注意:分数提交需要额外的反作弊验证,这不是 RBAC 能解决的——即使 player 有 score:submit 权限,分数本身还需要通过服务端校验。


定义ABAC(Attribute-Based Access Control) 是一种更灵活的权限模型,基于属性(Attributes) 做动态决策,而非预定义的角色。决策引擎会综合考量:

  • 用户属性:部门、职级、地域、入职时间
  • 资源属性:创建者、敏感级别、所属部门、文件类型
  • 环境属性:请求时间、IP 地址、设备类型、网络位置
  • 操作属性:读、写、删除、分享

一条 ABAC 策略看起来像这样:

IF 用户.部门 == 资源.所属部门
AND 用户.职级 >= "经理"
AND 环境.时间 IN 工作时间
AND 环境.IP IN 公司内网
THEN 允许 读取 敏感文档

为什么重要:RBAC 在简单场景下很好用,但当权限逻辑变得复杂时(特别是涉及数据归属上下文条件时),角色数量会爆炸。例如:“北京区域经理”、“上海区域经理”、“工作时间内的北京区域经理”… 这种 RBAC 的角色爆炸问题,ABAC 通过属性组合轻松解决。实践中,很多系统采用 RBAC + ABAC 混合模式:RBAC 处理粗粒度的功能权限,ABAC 处理细粒度的数据权限和上下文条件。

案例Google Drive — 文件权限完全是 ABAC 模式。决定你能否访问一个文件,取决于:

用户属性: 你是谁(user_id)、你属于哪个组织
资源属性: 文件创建者是谁、分享列表里有谁、是否"链接可见"
环境属性: 是否从公司设备访问(某些企业设置)
操作属性: 查看 vs 编辑 vs 评论
示例策略:
- 文件创建者 → 完全控制(owner)
- 在分享列表中 → 按分享权限(查看/评论/编辑)
- 链接分享开启且用户在同一组织 → 可查看
- 链接分享开启且设为"互联网可见" → 任何人可查看

这些规则用 RBAC 几乎无法表达(你不可能为每个文件创建一个角色),ABAC 是唯一合理的选择。

先想一想 🤔 News Feed 的内容可见性属于 RBAC 还是 ABAC?为什么?

点击查看解析

本质上是 ABAC

一条帖子能不能出现在你的 Feed 里,取决于:

  • 用户属性:你关注了谁、你的兴趣标签、你的地理位置
  • 资源属性:帖子的发布者是谁、帖子的可见范围(公开/仅好友/仅自己)
  • 关系属性:你和发布者是什么关系(好友/关注/陌生人)
  • 环境属性:帖子的发布时间(时效性)

这完全不是”角色”能处理的——不存在一个”能看张三帖子”的角色。可见性规则是基于用户之间的关系帖子本身的属性动态计算的,典型的 ABAC 场景。

混合使用:功能权限用 RBAC(管理员可以删除帖子、审核内容),数据可见性用 ABAC(谁能看到这条帖子)。


定义:不是所有认证都是”人”在登录。系统设计中有两种常见的非人类认证场景:

  1. API Key:一串随机字符串,用于标识和认证第三方开发者/应用。开发者在平台注册应用后获得 API Key,每次调用 API 时在请求头或 URL 参数中携带。平台通过 API Key 识别调用者身份、做访问控制和计费。特点:简单易用,但安全性有限(一旦泄露无法撤回,通常只用于服务端到服务端的调用,不应暴露在前端代码中)。

  2. 服务间认证(Service-to-Service Auth):微服务架构中,服务 A 调用服务 B 需要证明自己的身份。常见方案:

    • mTLS(双向 TLS):双方互相验证对方的证书,最安全但配置复杂
    • JWT + 服务账号:每个服务有自己的服务账号和密钥,签发短期 JWT 用于调用
    • API Gateway 统一认证:所有服务间调用经过网关,网关负责认证

为什么重要:在微服务架构中,服务间的网络调用可能被拦截或伪造(特别是跨网络段时)。如果内部服务之间不做认证,一旦攻击者攻入内网,可以随意调用任何内部 API。“零信任架构(Zero Trust)“的核心原则就是:不信任网络位置,每次调用都验证身份

案例Google Maps — 当开发者在自己的网站嵌入 Google Maps 时,需要申请一个 API Key。

https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg

Google 通过这个 API Key:

  • 识别调用者:知道是哪个开发者/项目在调用
  • 控制访问:API Key 可以限制只允许特定域名/IP 调用
  • 计费:按调用量计费,超过免费额度开始收费
  • 限流:防止某个开发者的应用过度调用影响服务

API Key 的安全最佳实践:限制来源(HTTP Referer 或 IP 白名单)、设置调用配额、定期轮换、区分前端 Key(受限)和后端 Key(全功能)。

先想一想 🤔 Search Engine 的爬虫服务需要调用索引服务来写入索引数据,应该用哪种服务间认证方案?

点击查看解析

推荐 mTLS 或 JWT 服务账号

方案一:mTLS(推荐)

  • 爬虫服务和索引服务各自有证书
  • 每次调用时双方互相验证证书
  • 优点:证书由基础设施层管理(如 Istio Service Mesh),应用代码无感知
  • 适合:服务数量多、有 Service Mesh 基础设施

方案二:JWT 服务账号

  • 爬虫服务有一个服务账号,用私钥签发 JWT
  • 索引服务用公钥验证 JWT
  • JWT 中包含服务身份和权限范围(如只允许写入索引,不允许删除)
  • 适合:服务数量少、没有 Service Mesh

不推荐 API Key:因为这是内部服务间通信,API Key 的安全性不够(无过期机制、不能携带权限信息)。API Key 更适合外部第三方接入。

关键点:无论用哪种方案,索引服务都应该验证调用者的权限范围——爬虫服务只能写入索引,不能删除全部索引或修改索引配置。


定义:自建认证系统(注册登录、密码加密、OAuth 集成、MFA 多因素认证、Session 管理…)是一项繁重且容易出错的工作。第三方认证服务(Authentication as a Service)将这些复杂功能打包为 SDK 和 API,让开发者可以快速集成完善的认证能力。

主流服务对比:

服务特点适合场景定价
Clerk开发体验极佳,预制 UI 组件完善,Next.js 集成丝滑中小项目快速启动免费 10,000 MAU
Supabase Auth开源,与 Supabase 数据库/存储生态深度集成已用 Supabase 的项目免费 50,000 MAU
Auth0企业级功能最全(RBAC、MFA、Breached Password Detection)企业级项目、合规要求高免费 25,000 MAU
Firebase AuthGoogle 生态,与 Firestore/Cloud Functions 集成Google Cloud 技术栈免费额度慷慨

选型决策树

需要自托管?→ Supabase Auth(开源可自部署)
Next.js 项目?→ Clerk(集成体验最好)
企业客户要求 SSO/SAML?→ Auth0(企业功能最全)
已用 Google Cloud?→ Firebase Auth
预算极低?→ Supabase Auth(开源免费)

为什么重要:认证系统看似简单(不就是比对密码吗?),但细节中全是安全坑:密码哈希算法选择(bcrypt vs argon2)、防暴力破解(限流+锁定)、密码重置流程(Token 有效期+一次性使用)、MFA 实现(TOTP 算法)、OAuth 回调安全… 这些功能自建需要数月,用第三方服务只需几小时。在项目早期,认证不应该是你的核心竞争力——除非你就是做认证服务的

案例:假设你的团队要为 11 个系统案例之一做 MVP:

  • 小团队(2-3人)做 URL Shortener:用 Clerk,几行代码搞定登录注册,专注核心功能(短链接生成和跳转)
  • 创业公司做 Hotel Reservation:用 Auth0,因为酒店行业需要企业客户 SSO 集成,Auth0 原生支持 SAML/OIDC
  • 用 Supabase 做 Gaming Leaderboard:直接用 Supabase Auth,数据库和认证在同一平台,开发效率最高
  • 大厂自研 Chat System:自建认证系统,因为有安全团队、有定制化需求、有合规要求

先想一想 🤔 什么情况下应该自建认证系统而不是用第三方服务?

点击查看解析

应该自建的情况

  1. 数据主权要求:金融、医疗、政府系统要求用户数据不能离开自有服务器
  2. 深度定制需求:认证流程高度定制化(如银行的多级审批登录、游戏的设备绑定认证)
  3. 规模经济:用户量极大(千万级),第三方按 MAU 计费会非常昂贵
  4. 核心业务:你本身就是做身份认证/安全相关产品的公司
  5. 已有安全团队:有专业的安全工程师团队能持续维护

不应该自建的信号

  • 团队没有专职安全工程师
  • 项目处于 MVP 阶段,需要快速验证
  • 团队在纠结”密码用什么算法加密”——说明认证经验不足
  • 把时间花在认证上意味着核心功能延期

务实的原则:先用第三方服务快速上线,等到第三方服务的限制真正成为瓶颈时再考虑自建或迁移。过早自建是典型的过度工程化。


练习一:为 Hotel Reservation 设计完整的认证 + 授权方案

Section titled “练习一:为 Hotel Reservation 设计完整的认证 + 授权方案”

要求

  1. 选择 JWT 还是 Session?说明理由
  2. 设计 RBAC 权限模型:列出所有角色、每个角色的权限列表
  3. 哪些场景需要 ABAC 补充?
  4. 是否需要 OAuth 第三方登录?如果需要,选择哪种模式?
  5. 是否需要 SSO?面向什么客户?

参考思路

认证方案: JWT(前后端分离,可能有移动端)
├── Access Token: 15分钟过期
├── Refresh Token: 30天过期,HttpOnly Cookie
└── 第三方登录: OAuth 2.0 授权码模式(Google/微信)
授权方案: RBAC + ABAC 混合
├── RBAC 角色:
│ ├── guest → 搜索、预订、查看自己的订单
│ ├── hotel_admin → 管理自己酒店的房间/价格/订单
│ └── platform_admin → 全局管理
├── ABAC 补充:
│ ├── hotel_admin 只能管理自己的酒店(资源归属)
│ ├── guest 只能查看/取消自己的预订(数据隔离)
│ └── 某些操作限制在工作时间(环境条件)
└── SSO:
└── 企业差旅客户通过 SAML/OIDC 接入公司账号体系

练习二:画出 OAuth 2.0 授权码模式的完整流程图

Section titled “练习二:画出 OAuth 2.0 授权码模式的完整流程图”

要求:画出以下参与方之间的完整交互:

  • 用户(浏览器)
  • 前端应用
  • 后端服务器
  • GitHub(OAuth Provider)

关键节点(确保你的流程图包含这些):

  1. 用户点击”用 GitHub 登录”
  2. 前端重定向到 GitHub 授权页
  3. 用户在 GitHub 上授权
  4. GitHub 回调带 code
  5. 后端用 code + client_secret 换 access_token
  6. 后端用 access_token 获取用户信息
  7. 后端创建/查找用户,签发自己的 JWT
  8. 前端拿到 JWT,后续请求携带