Keycloak如何结合应用系统进行认证与授权

本文只聚焦 Token 机制,按三个场景说明标准处理流程:

  1. 登录流程(如何发放与保存 token)
  2. 日常业务请求(如何带参、后端如何认证)
  3. 页面刷新与超时处理(正常刷新、过期刷新、失效重登)

一、登录流程

1)目标

登录成功后拿到三类信息并持久化:tokenTypeaccessTokenrefreshToken
其中 access token 用于业务请求,refresh token 用于续期。

2)前端请求参数

{
  "username": "xxx",
  "password": "xxx"
}

3)后端返回示例

{
  "code": 200,
  "msg": "",
  "data": {
    "tokenType": "Bearer",
    "accessToken": "....",
    "refreshToken": "....",
    "expires": 300000
  }
}

4)前端保存规范

  • 保存 accessToken"Bearer " + accessToken
  • 保存 refreshToken 供后续续期使用
  • 页面刷新后从持久化存储恢复,避免“刷新即掉线”

二、日常请求后端接口(携带参数 + 后端认证)

1)前端请求拦截器

所有业务请求统一自动注入请求头:

Authorization: Bearer <access_token>

业务接口无需每个页面手工拼 token,统一由拦截器处理。

2)后端认证方式(主流)

  • 从 Authorization 头读取 Bearer token
  • 使用 IDP 的 JWKS 做签名校验
  • 校验 issuer、exp、nbf、aud/azp 等声明
  • 校验通过后提取用户身份(sub/username/roles)进入业务层

3)aud/azp 的兼容建议

实战中 access token 可能出现 audazp 不完全一致,建议:

  • 优先匹配预期 audience
  • 同时允许按 client_id(azp)做兼容校验
  • 所有失败场景输出结构化日志,便于快速定位

三、界面刷新与超时处理(核心)

场景 A:正常刷新(F5)

用户 F5 后,前端从本地恢复 access token 并请求用户信息接口。若 token 仍有效,直接通过,不应弹“重新登录”。

场景 B:access token 过期,但 refresh token 有效

这是最常见场景,主流处理如下:

  1. 业务请求返回 401(或 token 过期语义)
  2. 前端不立即登出,先调用 /auth/refresh
  3. refresh 成功后更新本地 token
  4. 自动重放刚才失败的原请求
  5. 用户无感知继续使用系统

场景 C:refresh token 也失效

当 refresh 接口返回失败(例如 401),说明会话已彻底过期,此时才执行:

  • 清理本地 token
  • 弹出“请重新登录”提示
  • 跳转登录页

场景 D:并发请求同时 401

需避免“多次同时 refresh”。推荐“单飞刷新 + 队列重放”:

  • 第一条 401 触发 refresh
  • 其余 401 请求进入等待队列
  • refresh 成功后统一重放队列请求
  • refresh 失败后统一失败并跳登录

四、推荐的状态机(可直接落地)

已登录
  ├─ 请求成功 → 保持登录
  ├─ 请求401
  │   ├─ refresh成功 → 更新token → 重放请求 → 保持登录
  │   └─ refresh失败 → 清空token → 跳登录页
  └─ 主动退出 → 清空token → 跳登录页

五、验收清单

  • 登录后连续 F5,不应直接掉线
  • access token 过期时自动续期,不中断操作
  • refresh token 失效时,才提示重新登录
  • 并发请求下只触发一次 refresh,不产生风暴
  • Token 失败日志可区分:签名失败 / audience失败 / 已过期 / refresh失败

六、结论

这套方案本质是把“登录态维护”从一次性校验升级为“可续期会话”。
用户体验上,刷新页面与短期过期都应尽量无感;只有在 refresh 也失效时才重新登录。
这就是当前主流 Web 系统处理 token 生命周期的标准实践。

发表回复