2 分钟

现代框架如何处理认证与授权

了解现代框架如何实现认证与授权:会话、令牌、OAuth/OIDC、中间件、角色、策略,以及关键的安全陷阱。

现代框架如何处理认证与授权

认证 vs 授权:框架通常如何区分

认证回答“你是谁?”,授权回答“你被允许做什么?”。现代框架把它们视为相关但独立的关注点,这种分离是随着应用增长仍能保持安全一致性的主要原因之一。

认证:确定身份

认证是证明某个用户(或服务)就是其声称的身份。框架通常不会硬编码单一方法,而是提供扩展点以支持常见选项,如密码登录、社交登录、SSO、API 密钥和服务凭证。

认证的输出是一个身份:用户 ID、账号状态,有时还有基本属性(例如邮箱是否已验证)。重要的是,认证不应决定某个动作是否被允许——它只告诉你是谁在发出请求。

授权:决定访问

授权使用已建立的身份加上请求上下文(路由、资源所有者、租户、scopes、环境等)来决定某个动作是否被允许。这部分包含角色、权限、策略以及基于资源的规则。

框架将授权规则与认证分开,这样你可以:

  • 更换登录方法而无需重写访问规则
  • 在网页、API 和后台任务之间应用一致的权限检查
  • 将“你是谁”的逻辑与“你能做什么”的逻辑分离

强制点:框架在哪里应用规则

大多数框架通过请求生命周期中的集中点来执行规则:

  • 中间件/过滤器/拦截器,在控制器/处理器之前运行
  • 守卫(Guards),阻止对路由或动作的访问
  • 策略检查,在业务逻辑内部为特定资源做出决定

常见构建块(与框架无关)

尽管名称不同,构建块是熟悉的:一个 身份存储(用户和凭证),一个在请求间携带身份的 会话或令牌,以及始终如一地强制认证和授权的 中间件/守卫

本文的示例保持概念层面,便于你将其映射到所选框架。

身份存储与用户模型

在框架能“登录某人”之前,它需要两样东西:一个用于查找身份数据的位置(身份存储)和在代码中一致表示该身份的方式(用户模型)。现代框架中的许多“认证功能”都是围绕这两部分的抽象。

典型的身份来源

框架通常支持多种后端,内建或通过插件:

  • 应用数据库的用户:经典的 users 表/集合,由你的应用管理。
  • 外部身份提供者(IdP):Google、Microsoft、GitHub 或专用提供者如 Auth0/Okta,通常通过 OAuth 2.0 / OpenID Connect。
  • 企业目录:LDAP/Active Directory,常见于内部工具和 B2B 应用。

关键区别在于 谁是事实来源。使用数据库用户时,你的应用拥有凭证和档案数据。使用 IdP 或目录时,应用通常存储一个将外部身份映射到本地的“影子用户”。

核心用户模型字段

即便框架生成了默认用户模型,大多数团队也会标准化几个字段:

  • id:不可变的主键(最好不是邮箱)。
  • email/username:登录标识;通常唯一并规范化。
  • password_hash:仅当应用管理密码时存在(绝不存储明文密码)。
  • 状态标志:例如 is_verified, is_active, is_locked, deleted_at

这些标志很重要,因为认证不仅仅是“密码正确吗?”,还应判断“该帐号现在是否被允许登录?”

账号生命周期:不仅仅是注册

一个实用的身份存储应支持常见的生命周期事件:注册、邮箱/手机验证、密码重置、在敏感变更后撤销会话、以及停用或软删除。框架通常提供原语(令牌、时间戳、钩子),但你仍需定义规则:过期窗口、速率限制以及当账户被禁用时现有会话如何处理。

框架的插入点

大多数现代框架提供扩展点,如 user providersadaptersrepositories。这些组件把“给定登录标识,获取用户”和“给定用户 ID,加载当前用户”翻译成你选择的存储实现——无论是 SQL 查询、对 IdP 的调用,还是企业目录查找。

基于会话的认证(Cookies 与服务器会话)

基于会话的认证是许多 Web 框架仍然默认的“经典”方法——尤其适用于服务器渲染的应用。思路很简单:服务器记住你是谁,浏览器持有指向这段记忆的小指针。

工作原理

登录成功后,框架在服务端创建一个会话记录(通常是随机的 session ID 对应到某个用户)。浏览器收到包含该 session ID 的 cookie。在每次请求中,浏览器会自动发送该 cookie,服务器用它查找已登录的用户。

由于 cookie 只是一个标识符(而不是用户数据本身),敏感信息保存在服务器端。

现代框架试图通过设置安全默认值让会话 cookie 更难被窃取或滥用:

  • HttpOnly:阻止 JavaScript 读取 cookie(有助于降低 XSS 的破坏)。
  • Secure:只在 HTTPS 上发送 cookie。
  • SameSite (Lax/Strict/None):控制跨站点发送 cookie(对 CSRF 防护和第三方 auth 流程很重要)。

你通常会在“session cookie 设置”或“安全头”下看到这些配置。

会话的存储位置

框架通常让你选择会话存储:

  • 内存(In-memory):快速且易用,但重启后会话丢失,且不易扩展到多台服务器。
  • 数据库存储:持久且可审计,但增加查询开销。
  • 缓存/Redis 类存储:快速并可在服务器间共享;适合扩展,但依赖外部服务。

总体上,权衡是速度 vs 持久性 vs 运营复杂度。

注销与使失效

注销可以意味着两种不同的事情:

  • 单设备注销:删除当前会话并清除 cookie。
  • 全部注销:使该用户的所有会话失效(例如在密码变更后)。

框架通常通过跟踪用户的“会话版本”、为用户存储多个 session ID 并撤销它们来实现“全部注销”。如果需要更强的即时撤销能力,会话基于服务器的方法通常比纯令牌更简单,因为服务器可以立即忘记某个会话。

基于令牌的认证(JWT 与 不可见令牌)

基于令牌的认证用一个字符串替代服务器端会话查找。令牌在登录后颁发,客户端在后续请求中携带它。框架通常建议在以下场景使用令牌:服务器主要作为 API(被多个客户端使用)、移动应用、SPA 与独立后端交互,或服务间需要互相调用而无法使用浏览器会话时。

“令牌”在实践中的含义

令牌是在登录或 OAuth 流程后颁发的访问凭证。客户端在后续请求中携带它,以便服务器认证调用方并进行授权。大多数框架将其视为一等模型:包含“颁发令牌”的端点、验证令牌的认证中间件,以及身份建立后运行的守卫/策略。

不可见令牌 vs JWT

不可见(opaque)令牌 是没有对客户端意义的随机字符串(例如 tX9...)。服务器通过查找数据库或缓存条目来验证它们。这使撤销变得简单,并且令牌内容对外部不可见。

JWT(JSON Web Tokens) 是结构化且签名的。JWT 通常包含声明,比如用户标识(sub)、发行者(iss)、受众(aud)、签发/过期时间(iat, exp),有时还有 roles/scopes。重要的是:JWT 默认是编码而不是加密——任何持有该令牌的人都能读取其声明,即便不能伪造它。

存储:Authorization 头 vs Cookies

框架建议的两个更安全的默认选项通常是:

  • 对于 API,通过 Authorization: Bearer \u003ctoken\u003e 头发送访问令牌。这避免了自动发送 cookie 带来的 CSRF 风险,但要求更强的 XSS 防御,因为 JavaScript 通常可以读取并附加令牌。
  • 仅在你能将 cookie 设为 HttpOnlySecure 并正确处理 CSRF 的情况下使用 cookie(通常与单独的 CSRF 令牌配合)。

刷新令牌、旋转与端点

访问令牌应短期有效。为了避免频繁登录,许多框架支持 刷新令牌:一种长期有效但仅用于 mint 新访问令牌的凭证。

常见结构是:

  • POST /auth/login → 返回 access token(和 refresh token)
  • POST /auth/refresh → 旋转 refresh token 并返回新的 access token
  • POST /auth/logout → 在服务器端使 refresh token 失效

每次旋转时发放新的刷新令牌可以限制刷新令牌被盗用的损害,许多框架提供钩子来存储令牌标识符、检测重用并快速撤销会话。

OAuth 2.0 与 OpenID Connect 在框架生态中的实践

启动安全后端
创建基于 Go + PostgreSQL 的认证就绪后端,并安全迭代规则。

OAuth 2.0 与 OpenID Connect(OIDC)常被一起提及,但框架会区别对待它们,因为它们解决的问题不同。

OAuth 2.0 vs OIDC:你真正需要哪个

使用 OAuth 2.0 当你需要 委托访问:你的应用获得调用某个 API 的权限以用户名义操作(例如读取日历或向仓库发布),无需处理用户密码。

使用 OpenID Connect 当你需要 登录/身份:你的应用想知道 谁是用户,并接收包含身份声明的 ID token。在实践中,“使用 X 登录” 通常是 在 OAuth 2.0 之上的 OIDC

框架通常支持的核心流程

大多数现代框架及其认证库关注两种流程:

  • Authorization Code flow + PKCE:浏览器应用和移动客户端的默认选择。PKCE 有助于防止授权码被截取,且被大多数提供者要求或推荐。
  • Client Credentials flow:用于无端用户的服务间调用(作业、后端工作者、内部微服务)。

回调处理:安全细节很重要的地方

框架集成通常提供回调路由和辅助中间件,但你仍需正确配置关键项:

  • 精确验证 redirect URI(包括 scheme/host/path),避免通配符重定向 URI。
  • 使用并验证 state 参数以防止类似 CSRF 的登录攻击。
  • 对 OIDC 生成并验证 nonce 以减少令牌重放风险。
  • 将临时值(state/nonce/verifier)存储在安全会话或加密 cookie 中,而不是 localStorage。

scopes、claims 与映射到本地用户

框架通常把提供者的数据规范化到本地用户模型。关键设计决策是哪些东西实际驱动授权:

  • Scopes 是 OAuth 的 API 权限(访问令牌能做什么)。
  • Claims 是 OIDC ID token 中的身份属性(用户是谁)。

常见做法是:将稳定标识(如 sub)映射到本地用户,然后把提供者的角色/组/声明翻译成本地的角色或策略,由你的应用控制。

密码、哈希、MFA 与账号恢复

密码仍然是许多应用默认的登录方式,所以框架往往自带更安全的存储模式和常见护栏。核心规则不变:绝不应在数据库中存储明文密码(或简单哈希)。

密码哈希默认(以及为什么简单哈希不安全)

现代框架及其认证库通常默认使用专用密码哈希算法,如 bcryptArgon2scrypt。这些算法故意运算较慢并包含 salt,能防止预计算表攻击并使大规模破解变得昂贵。

简单的加密哈希(如 SHA-256)不适合密码,因为它们设计为快速。如果数据库泄露,快速哈希会让攻击者能快速猜测数十亿密码。密码哈希器提供可调的工作因子(cost),以便随着硬件进步调整安全性。

你常会看到的密码策略

框架通常提供钩子(或中间件/插件)来强制执行合理规则而不必在每个端点中硬编码:

  • 以长度为先 的策略(更长的密码/短语比复杂但短的规则更有效)。
  • 对已泄露密码的检查(即不允许使用已被曝光的密码)。
  • 速率限制 与可选的 临时锁定 在多次失败后减慢暴力破解尝试。

MFA 选项与权衡

大多数生态支持在密码验证后添加 MFA 作为二次步骤:

  • TOTP(验证码应用):广泛支持、离线可用;若用户被诱导输入验证码仍可能被钓鱼。
  • WebAuthn / passkeys:对抗钓鱼和重放非常有效;一旦设置,通常能提供最佳体验。
  • 短信验证码:部署相对容易,但因 SIM 换绑和拦截风险较弱——比没有强,但不适合高风险账户。

安全的账号恢复

密码重置是常见的攻击路径,框架通常鼓励如下模式:

  • 基于一次性令牌的重置链接,这些令牌在服务器端存储(通常像密码一样哈希)。
  • 短期过期(分钟到数小时)并强制一次性使用。
  • 在重置成功后 使会话失效 或旋转令牌,以防止已窃会话继续存在。

一条好规则:让合法用户的恢复过程简单,但让攻击者自动化成本高昂。

中间件、守卫与请求生命周期

大多数现代框架把安全作为请求流水线的一部分:一系列在控制器/处理器之前(有时之后)运行的步骤。名称各异——中间件、过滤器、守卫、拦截器——但理念一致:每一步可以读取请求、附加上下文或终止处理。

一个实用的流水线心智模型

典型流程如下:

  1. 路由 选择端点(例如 /account/settings)。
  2. 预处理组件 运行(中间件/过滤器/拦截器)。
  3. 认证 试图识别调用方。
  4. 授权 决定已识别的调用方是否可以访问端点。
  5. 处理器/控制器 执行业务逻辑。
  6. 后处理 可能转换响应或记录细节。

框架鼓励你把安全检查放在业务逻辑之外,让控制器专注于“做什么”,而不是“谁能做”。

认证发生在哪里(先建立身份)

认证是框架从 cookie、session ID、API key 或 bearer token 建立 用户上下文 的步骤。如果成功,它会创建一个请求作用域的身份对象——通常暴露为 user, principalcontext.auth

这个附件很关键,因为后续步骤(以及你的应用代码)不应反复解析头或重新验证令牌。它们应读取已填充的用户对象,通常包含:

  • 一个稳定的用户 ID
  • roles/claims(有时)
  • 认证方式或会话年龄等元数据

授权发生在哪里(权限检查)

授权通常实现为:

  • 路由级别的守卫(例如“必须已登录”)
  • 策略检查(例如“是否可以编辑此文档”),在加载资源后评估

第二种类型解释了为什么授权钩子常靠近控制器和服务:它们可能需要路由参数或数据库加载的对象才能做出正确决定。

401 vs 403:清晰地处理失败

框架区分两种常见失败模式:

  • 401 Unauthorized(未认证):未建立有效身份。通常对浏览器应用触发重定向到登录页,对 API 返回 JSON 错误。
  • 403 Forbidden(未被授权):已知身份但缺乏权限。

设计良好的系统在 403 响应中避免泄露细节;它们直接拒绝访问而不解释是哪个规则失败了。

授权模型:角色、权限与策略

规划授权模型
先映射角色、权限和端点,再让应用按计划执行。

授权回答一个更窄的问题:“已登录的用户现在是否被允许做这件特定的事?”现代框架通常支持多种模型,许多团队会组合使用它们。

基于角色的访问控制(RBAC)

RBAC 把用户分配给一个或多个角色(例如 admin, support, member),并根据角色控制功能访问。

它易于理解和快速实现,尤其当框架提供诸如 requireRole('admin') 的辅助函数时。角色层级(“admin 隐含 manager 隐含 member”)可以减少重复,但也可能隐藏权限:对父角色的小改动可能在应用中悄然授予权限。

RBAC 适合用于粗粒度且稳定的区分。

基于权限的访问(精细化)

基于权限的授权会针对动作与资源做检查,通常表示为:

  • 动作read, create, update, delete, invite
  • 资源invoice, project, user,有时带 ID 或所有权

这个模型比 RBAC 更精确。例如,“可以更新项目”不同于“只能更新自己拥有的项目”,后者需要同时检查权限与数据条件。

框架通常通过中央的 can? 函数(或服务)来实现,从控制器、解析器、工作器或模板中调用。

基于策略的授权(带条件的规则)

策略把授权逻辑打包成可复用的评估器:"如果用户是作者或是版主,则允许删除评论。"策略可以接受上下文(用户、资源、请求),非常适合:

  • 所有权检查
  • 订阅等级规则
  • 基于时间或组织的约束

当框架将策略集成到路由和中间件中时,你可以在各端点之间一致地强制这些规则。

注解/标注 vs 基于代码的检查

注解(例如 @RequireRole('admin'))把意图放在处理器附近,但当规则复杂时可能变得分散。

基于代码的检查(显式调用授权器)更啰嗦,但通常更易于测试和重构。常见折中是:用注解做粗粒度门槛,用策略做详细逻辑。

常见内置防护:CSRF、CORS 与安全头

现代框架不仅帮助你登录用户——它们还提供对围绕认证发生的最常见“Web 粘合”攻击的防御。

如果你的应用使用会话 cookie,浏览器会自动把它们附加到请求——有时即便请求由另一个站点触发也会发送。框架的 CSRF 防护通常会增加一个每会话(或每请求)的 CSRF 令牌,必须和有状态改变的请求一起发送。

常见模式:

  • 同步令牌(Synchronizer token):服务器在表单中渲染令牌,并在 POST/PUT/PATCH/DELETE 时验证。
  • 双重提交 cookie(Double-submit cookie):CSRF 令牌存储在 cookie 中并在头/体中发送;服务器检查两者是否匹配。

将 CSRF 令牌与 SameSite cookie(通常默认 Lax)配合使用以降低风险,并确保你的 session cookie 在适当场景下为 HttpOnlySecure

CORS:API 需要显式规则

CORS 不是认证机制;它是浏览器的权限系统。框架通常提供中间件/配置以允许受信任的来源调用你的 API。

需避免的错误配置:

  • Access-Control-Allow-Origin: *Access-Control-Allow-Credentials: true 一起使用(浏览器会拒绝,且表明配置混乱)。
  • 反射任何 Origin 头而不使用严格允许列表。
  • 忘记允许必要的头(如 Authorization)或方法,导致客户端“curl 能行但浏览器失败”。

点击劫持与安全头

大多数框架可以设置安全默认值或方便添加以下头:

  • X-Frame-OptionsContent-Security-Policy: frame-ancestors 防止点击劫持。
  • 更广泛的 Content-Security-Policy 用于控制脚本/资源来源。
  • Referrer-PolicyX-Content-Type-Options: nosniff 改善浏览器行为安全。

输入验证 vs 授权

验证确保数据格式正确;授权确保用户被允许执行该操作。合法的请求仍可能被拒绝——最佳实践是在早期校验输入,然后对访问的特定资源执行权限校验。

按应用类型的模式:SSR、SPA、移动、微服务

添加移动端客户端
创建 Flutter 客户端,并配套适合移动端的令牌认证。

“正确”的认证模式在很大程度上取决于代码在哪里运行以及请求如何到达你的后端。框架可能支持多种选项,但在一种应用类型中看起来自然的默认在另一种场景下可能笨拙或有风险。

服务器渲染应用(SSR)

SSR 框架通常与基于 cookie 的会话配合得最好。浏览器自动发送 cookie,服务器查找会话,页面可在渲染时带上用户上下文而无需额外客户端代码。

实用规则:保持会话 cookie 为 HttpOnlySecure,并选择合理的 SameSite 设置;对每个渲染私有数据的请求依赖服务器端授权检查。

单页应用(SPA)

SPA 常由 JavaScript 调用 API,这使得令牌选择更明显。许多团队偏好 OIDC 流程以获得短期访问令牌。

当可行时避免将长期令牌存储在 localStorage 中,因为它会增加 XSS 的影响面。常见替代是 BFF(backend-for-frontend)模式:SPA 与你自己的服务器用会话 cookie 通信,服务器为上游 API 交换/保存令牌。

移动客户端

移动应用不能以同样方式依赖浏览器 cookie 规则。它们通常使用带 PKCE 的 OAuth/OIDC,并将刷新令牌存储在平台的安全存储中(Keychain/Keystore)。

为“丢失设备”恢复做准备:撤销刷新令牌、旋转凭证,并让重新认证过程尽量顺畅——尤其在启用 MFA 时。

微服务与 API 网关

在多服务场景下,你会在集中式身份与服务级别强制之间做选择:

  • 网关中心化(Gateway-centric):网关验证令牌并转发身份上下文。
  • 深度防御(Defense in depth):每个服务也验证令牌并为自己的资源强制授权。

对于服务到服务的认证,框架通常集成 mTLS(强通道身份)或 OAuth client credentials(服务账户)。关键是既要认证调用方,又要授权其能做什么。

模拟(Impersonation)与管理员访问

管理员“模拟用户”功能强大且危险。优先使用显式的模拟会话,要求管理员重新认证/MFA,并始终写审计日志(谁在何时模拟了谁,以及执行了哪些操作)。

测试、可观测性与常见陷阱

安全功能只有在代码变化时仍然可用才有意义。现代框架让测试认证与授权更容易,但你仍需编写反映真实用户行为与真实攻击者行为的测试。

在不脆弱的设置下测试认证流程

先把测试内容分开:

  • 授权规则的单元测试(策略、守卫、权限检查)。这些应快速并覆盖边界情况,如“用户拥有资源” 与 “管理员覆盖”。
  • 受保护路由的集成测试(应通过或应被拒绝的请求)。这些能捕捉中间件错接、缺失的装饰器和破损的重定向。

大多数框架都带有测试辅助工具,因此你不必每次都手写会话或令牌。常见模式包括:

  • 能跨请求保留 cookie 的 测试客户端(对基于会话的认证有用)。
  • 用于 模拟用户登录 的辅助工具(或附加 JWT/opaque 令牌)而无需通过 UI。
  • 用户、角色与资源的 fixtures/factories,让测试更可读。

实用规则:每个“正常路径”测试都应有一个“应被拒绝”测试,以证明授权检查实际被执行。

如果你在这些流程上快速迭代,支持快速原型和回滚的工具会很有帮助。例如,Koder.ai(一个 vibe-coding 平台)可以从基于聊天的规范生成 React 前端和 Go + PostgreSQL 后端,然后让你使用快照与回滚在细化中间件/守卫与策略检查时保持可审计——在你试验会话与令牌方案时尤其有用。

可观测性:证明发生了什么,而不是你希望发生的事

当出现问题时,你需要快速且可靠的答案。

记录和/或审计关键事件:

  • 认证事件:登录成功/失败、MFA 挑战、密码重置、令牌刷新。
  • 授权拒绝:哪个策略失败、在什么资源上、哪个用户(避免记录秘密)。
  • 关联 ID(Correlation IDs):请求 ID 在日志和追踪中传播,以便追踪一次登录尝试跨服务的流程。

也要添加轻量级指标:401/403 响应率、失败登录激增、异常的令牌刷新模式。

框架不能完全替你避免的常见陷阱

  • 信任客户端声明:不要依赖 UI 标志或客户端侧的“角色”;一定要在服务器端强制执行。
  • 在次要端点漏检:导出、后台作业、管理工具和“内部” API 仍然需要授权。
  • 过宽的 scope/角色:“先这样可以了”的权限往往会成为永久设置。
  • 令牌泄露:把令牌存到易被复制的地方(日志、URL、localStorage)或发送给第三方。

将认证/授权错误视为可测试的行为:如果它可能回归,就应该为它写测试。

常见问题

在框架中,认证和授权的实际区别是什么?

认证证明身份(谁在发出请求)。授权决定访问权限(该身份在当前上下文中可以做什么),会考虑路由、资源所有权、租户和 scopes 等因素。

框架通常将两者分离,这样可以在不重写权限逻辑的情况下更换登录方法。

框架通常在哪里“应用”认证和授权检查?

大多数框架在请求管线中执行认证/授权,通常包括:

  • 中间件/过滤器/拦截器来解析会话或令牌并附加 user/principal
  • 路由守卫来阻止未认证或未授权的请求
  • 在业务逻辑附近进行的策略检查,用于资源特定的决策
什么是身份存储,它与用户模型有什么不同?

身份存储(identity store)是用户和凭证的真相来源(或是对外部身份的映射)。用户模型是代码中表示该身份的方式。

在实践中,框架需要两者来回答:"给定这个标识符或令牌,当前用户是谁?"

框架通常集成哪些典型的身份来源?

常见的身份来源包括:

  • 应用数据库(你拥有凭证和个人资料数据)
  • 外部 IdP(基于 OIDC/OAuth 的提供者,如 Google/Microsoft)
  • 企业目录(LDAP/Active Directory)

使用 IdP/目录时,很多应用会在本地保留一个“影子用户”以便将稳定的外部 ID(如 OIDC 的 sub)映射到应用内角色和数据。

什么时候应该使用基于会话的认证 vs 基于令牌的认证?

会话(session)把身份保存在服务器端,浏览器持有指向该会话的 cookie(session ID)。它们适合 SSR,并且使撤销变得简单。

令牌(JWT/opaque)每次请求都携带,通常通过 Authorization: Bearer ... 发送,适合 API、SPA、移动端和服务间通信。

哪些 cookie 标志对会话安全最重要,为什么?

框架通常通过以下方式加固会话 cookie:

  • HttpOnly(减少 XSS 导致的 cookie 被窃取)
  • Secure(仅通过 HTTPS 发送)
  • SameSite(限制跨站点发送;影响 CSRF 和第三方登录流程)

你仍需根据应用场景选择合适的值(例如,跨站点流程可能需要 None)。

不可见令牌和 JWT 有何不同,为什么重要?

不可见(opaque)令牌是随机字符串,需要服务器 lookup 来验证(易于撤销,内容对客户端不可见)。

JWT 是签名的、包含可读声明的自包含令牌(例如 sub, exp, roles/scopes)。它们在分布式系统中方便,但撤销更难,通常需要短过期时间和服务器端控制(黑名单、版本等)。

现代框架中刷新令牌和旋转是如何工作的?

让访问令牌短期有效,只用刷新令牌来换取新的访问令牌。

典型端点:

  • POST /auth/login → 返回 access + refresh
  • POST /auth/refresh → 旋转 refresh 并返回新 access
  • POST /auth/logout → 在服务器端使 refresh 失效

通过旋转并检测重用,可以限制刷新令牌被盗用时的影响。

我需要 OAuth 2.0、OpenID Connect 还是两者都需要?

OAuth 2.0 用于委托访问(让应用代表用户调用 API,不直接处理用户密码)。

OIDC 用于登录/身份(想知道“这个用户是谁?”),它在 OAuth 2.0 之上提供 ID token 和标准化的身份声明。

“使用 X 登录” 通常是基于 OAuth 2.0 的 OIDC。

角色、权限和策略如何组合用于授权?

RBAC(角色)适合用于粗粒度的访问控制(如 admin vs member)。权限/策略用于更细粒度的规则(如只允许编辑自己拥有的文档)。

常见模式:

  • 使用角色做粗粒度路由守卫
  • 使用策略在资源级别基于 user + resource + request 上下文做决策

Related posts