news 2026/7/6 7:03:54

微服务认证与授权:06 — Keycloak / IdP

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微服务认证与授权:06 — Keycloak / IdP

📦 GitHub: https://github.com/geekchow/micro-service-auth

Keycloak是本 PoC 的身份提供方(Identity Provider):它对用户进行认证、拥有会话状态,并签发驱动一切下游授权决策的 JWT。

什么是 IdP

IdP(身份提供方)是负责认证用户并签发令牌的系统。完整术语表见 01 — 概念。

简而言之:

  • IdP 证明用户是谁
  • 其他系统决定该用户能做什么

本项目为什么需要 IdP

如果没有 IdP,每个服务都得各自实现并维护自己的登录逻辑、令牌签发逻辑、密码处理、用户存储与声明管理。

那会造成:

  • 重复的安全代码
  • 各服务之间不一致的身份规则
  • 更难的审计与排查
  • 更难与网关、策略引擎集成

本项目使用Keycloak作为 IdP,从而把身份集中化:

  • 一个统一的地方认证用户
  • 一个统一的地方管理像customerops-admin这样的角色
  • 一个统一的地方签发 JWT
  • 一个统一的地方定义像customer_idaccount_ids这样的声明

Keycloak 在本 PoC 中的位置

User or demo script

Keycloak

JWT access token

Kong

OPA

banking-api-service

identity-bootstrap-service

Keycloak不是网关、不是策略引擎、也不是银行 API。它是身份与令牌声明的来源。

Keycloak 如何工作

Realm

realm 是一个安全边界,拥有自己的用户、client、角色与令牌设置。

本项目使用 realmbanking-poc。所有演示用户与 client 都位于该 realm 内。

用户

用户是用于登录的身份。本 PoC 中的演示用户是:

  • alice
  • ops-admin

identity-bootstrap-service通过 Keycloak 管理 API 创建并管理这些用户,设置如下属性:

  • customer_id
  • account_ids
  • demo_managed

角色

角色代表粗粒度的权限分组。本 PoC 使用两个 realm 角色:

  • customer
  • ops-admin

这些角色出现在 JWT 中,被KongOPAbanking-api-service使用。

Client

client 是与 Keycloak 交互的应用或服务。本仓库定义了两个:

  1. mobile-banking-app—— 公共 client,演示登录流程用它来获取访问令牌(directAccessGrantsEnabled: truepublicClient: true
  2. kong-introspection—— 机密的服务账户 client(publicClient: falseserviceAccountsEnabled: true),由Kong用来内省令牌

协议映射器(Protocol Mappers)

协议映射器控制哪些声明进入令牌。mobile-banking-app映射了:

  • customer_id—— 来自用户属性,写入访问令牌、ID 令牌与 userinfo
  • account_ids—— 来自用户属性(多值),写入访问令牌、ID 令牌与 userinfo
  • 受众mobile-banking-app—— 仅写入访问令牌

这些声明会流向下游:Kong把它们转发给OPAOPA在策略中使用它们,banking-api-service用它们做纵深防御检查。

令牌

登录成功后,Keycloak 签发一个签名的 JWT 访问令牌,包含:

  • sub
  • preferred_username
  • aud
  • iss
  • exp
  • realm_access.roles
  • customer_id
  • account_ids

该令牌由 Keycloak 签名,从而让下游系统能够以密码学方式校验它。

本项目中的 OAuth 2.0 与 OpenID Connect

Keycloak 讲的是标准的身份协议。

OAuth 2.0

OAuth 2.0 是一套用于委托访问的框架。它提供了获取访问令牌、并在调用 API 时使用这些令牌的标准方式。

OpenID Connect

OpenID Connect 是建立在 OAuth 2.0 之上的身份层。它标准化了身份声明与端点。

实践中:

  • Keycloak 认证用户
  • Keycloak 签发兼容 OIDC 的 JWT
  • 服务用这些令牌来识别调用方

这里使用的流程

演示脚本使用直接的用户名/密码令牌交换(directAccessGrantsEnabled)来对接 Keycloak。

对本 PoC 而言重要的是:

  1. 凭据发送给 Keycloak
  2. Keycloak 校验凭据
  3. Keycloak 返回一个签名的 JWT 访问令牌
  4. 该令牌被发送到Kong以及银行 API 路径上

Keycloak 的会话与令牌活跃性

Keycloak 拥有 JWT 背后的实时会话状态 —— 这正是为什么即便对一个结构上合法的 JWT,令牌内省也可能回答active: false。完整的内省机制见 11 — JWT 签名、校验与内省。

逻辑会话类型

Keycloak 跟踪三层会话状态:

  1. 认证会话(authentication session,短暂)—— 登录流程期间的临时状态;登录完成或过期后移除
  2. 用户会话(user session)—— 表示某个 realm 中被认证的用户;跟踪开始时间、空闲/过期状态与登出状态
  3. 客户端会话(client session,按 client 划分)—— 为每个 client(如mobile-banking-app)附着在某个用户会话上;跟踪该 client 在此次登录会话中的参与情况

物理存储

运行时,Keycloak 把在线会话状态存放在 Infinispan 缓存中。在集群部署里,这些缓存分布在各节点上。离线会话则持久化在数据库中。

关键的实践要点:令牌声明随 JWT 一同传输,但实时会话状态存放在 Keycloak 的服务端。这正是为什么一个令牌可以被正确解码,而内省仍可能返回active: false

关于访问令牌/刷新令牌的生命周期、以及它们与会话状态的关系,详见 13 — 访问令牌与刷新令牌的生命周期。

令牌签发与校验流程

banking-api-serviceKongKeycloakUserbanking-api-serviceKongKeycloakUserusername + passwordauthenticate usersigned JWT access tokenAPI request + bearer tokenintrospect tokenactive or inactiveforward allowed requestfetch JWKS (for signature validation)validate issuer + audience + signature + expiryAPI response

为什么登录之后仍然需要校验 JWT

一个常见的误解:

“Keycloak 已经认证过用户了,所以服务不需要再次校验令牌。”

这是错的。一旦令牌离开 Keycloak,下游系统仍必须验证:该令牌确实由 Keycloak 签发、是发给本应用的、尚未过期、且未被篡改。

这正是为什么本 PoC 在多个地方校验令牌:

  • Kong用 Keycloak 做内省
  • banking-api-service校验 JWT 的签名、签发者与受众

Keycloak 在本仓库中如何配置

主配置文件是infra/keycloak/realm-export.json

从该文件核实的关键设置:

设置
Realmbanking-poc
Realm 角色customerops-admin
公共 clientmobile-banking-appdirectAccessGrantsEnabled: true
机密 clientkong-introspectionserviceAccountsEnabled: true
协议映射器customer_idaccount_ids(用户属性),aud=mobile-banking-app
用户档案属性customer_id(单值)、account_ids(多值)—— 仅管理员可编辑

realm-export 还声明了用户档案(user-profile)schema,以便identity-bootstrap-service能安全地写入customer_idaccount_ids属性。

Keycloak 如何与其他组件协作

Keycloak 与 identity-bootstrap-service

bootstrap 服务使用 Keycloak 管理 API 来:

  • 创建演示用户
  • 设置密码
  • 分配 realm 角色
  • 设置自定义属性(customer_idaccount_idsdemo_managed

这让 PoC 无需手动配置 Keycloak 即可重复运行。

Keycloak 与 Kong

Kong在转发请求或询问OPA决策之前,使用 Keycloak 令牌内省来检查令牌是否处于 active。Kong使用kong-introspection机密 client 的凭据向 Keycloak 认证。

Keycloak 与 OPA

OPA不直接与 Keycloak 通信。取而代之的是:

  • Keycloak 在 JWT 中签发声明
  • Kong在内省后读取经校验的令牌上下文
  • Kong把相关声明发给OPA
  • OPA在策略中使用这些声明

所以 Keycloak 是通过令牌声明间接影响OPA的决策。

Keycloak 与 banking-api-service

banking-api-service信任 Keycloak 作为令牌签发者,但会独立校验:

  • 签名(通过 JWKS)
  • 签发者
  • 受众

然后读取诸如realm_access.rolescustomer_idaccount_ids之类的声明,用于服务端的授权检查。

本 PoC 中的声明流转

issues JWT with roles customer_id account_ids

introspect token

send claims to OPA

allow or deny

forward request

validate JWT again

use claims for defense in depth

Keycloak

Kong

OPA

banking-api-service

Response

本 PoC 中的实际示例

示例 1:alice 访问她自己的账户

Keycloak 为alice签发一个令牌,包含:

  • 角色customer
  • customer_id=C-1001
  • account_ids=[A-1001]

随后:

  • Kong确认令牌处于 active
  • OPA看到A-1001在令牌声明中
  • banking-api-service再次检查同一组声明
  • 请求被允许

示例 2:alice 访问另一个账户

如果alice请求账户A-2001

  • 该令牌仍然是一个有效的身份令牌
  • 但声明并不授权访问A-2001
  • OPA返回 deny
  • Kong返回403

这体现了关键思想:有效的身份并不自动意味着有效的授权。

示例 3:ops-admin 的访问

如果用户具备ops-admin角色:

  • OPA允许更宽的访问
  • banking-api-service也看到该角色并在服务端允许访问

为什么 Keycloak 在这里很合适

Keycloak 提供了:

  • 集中化的认证
  • 标准的令牌签发(OIDC/OAuth 2.0)
  • 通过协议映射器支持自定义声明
  • 用于自动化演示初始化的管理 API
  • 面向网关与服务的标准集成模式

它让项目能够专注于银行授权逻辑,而不必重新发明登录基础设施。

常见误解

“Keycloak 已经处理了所有安全”

不。Keycloak 处理身份与令牌签发。它不替代网关执行(Kong)、策略评估(OPA)或业务服务检查(banking-api-service)。

“OPA 可以替代 Keycloak”

不。OPA是 PDP —— 它判定策略。它不认证用户、也不签发令牌。

“Kong 可以替代 Keycloak”

不。Kong是 PEP —— 网关。它不是身份提供方。

“Spring Boot 自己全干了不就行”

技术上它能做更多,但那样会把身份、策略与业务逻辑塌缩到一个地方,使架构更难维护、更难理解。

小结

  1. Keycloak 认证用户
  2. Keycloak 签发携带身份与权益声明的 JWT
  3. Kong检查令牌活跃性,并向OPA请求授权决策
  4. banking-api-service再次校验 JWT 并执行服务端检查

这就是 Keycloak 在本项目中的意义:它是那个以标准、集中、可重复的方式让其余安全流程得以成立的系统。


← Prev: 05 — 组件巡览 · Next: 07 — Kong →


📚 返回专栏目录

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 7:03:01

STM32与PCF8591混合信号处理方案设计与实现

1. 项目概述:PCF8591与STM32F745VG的混合信号处理方案在嵌入式系统开发中,模拟信号与数字信号的相互转换是连接物理世界与数字世界的桥梁。PCF8591这颗集成了ADC和DAC功能的I2C接口芯片,配合STM32F745VG这款高性能ARM Cortex-M7内核微控制器&…

作者头像 李华
网站建设 2026/7/6 7:02:55

PCF8591与PIC18F47Q10的ADC/DAC信号转换系统设计

1. PCF8591模块的核心特性解析PCF8591是一款采用I2C接口的8位精度ADC/DAC转换芯片,在嵌入式信号处理领域有着广泛应用。这款芯片最显著的特点是集成了4路模拟输入通道和1路模拟输出通道,采用单电源供电(2.5V-6V),采样率…

作者头像 李华
网站建设 2026/7/6 7:02:49

BLDC电机FOC控制:A89307与PIC18F86K22的硬件设计

1. 项目背景与核心挑战在工业自动化、无人机和电动汽车等领域,无刷直流电机(BLDC)因其高效率、长寿命和低维护需求已成为主流选择。但实现高性能BLDC控制面临三大技术挑战:高电流控制难题:15A级电流对驱动电路的散热设计、PCB布局和MOSFET选型…

作者头像 李华
网站建设 2026/7/6 7:02:00

DS28EC20与PIC18F96J65在嵌入式存储中的优化应用

1. 为什么选择DS28EC20与PIC18F96J65组合?在嵌入式系统中保存用户设置和偏好,通常需要考虑几个关键因素:非易失性存储的可靠性、接口复杂度、功耗以及成本。DS28EC20作为1-Wire接口的EEPROM芯片,与PIC18F96J65微控制器的组合&…

作者头像 李华
网站建设 2026/7/6 7:00:16

因子分析与主成分分析对比:基于23家上市公司21项财务指标的R语言建模

因子分析与主成分分析实战对比:基于R语言的财务指标建模指南 面对23家上市公司21项财务指标的海量数据,如何快速提取关键信息并建立有效模型?这不仅是金融分析师日常面临的挑战,更是数据科学家需要掌握的核心技能。主成分分析(PCA…

作者头像 李华
网站建设 2026/7/6 6:57:04

嘉立创EDA专业版SMT下单:从Gerber到PCBA的7个关键文件与3大避坑点

嘉立创EDA专业版SMT下单全流程:7大核心文件与3个实战避坑指南在硬件开发领域,从设计到量产的最后一步往往充满挑战。作为国内领先的一站式硬件创新服务平台,嘉立创的SMT贴片服务已成为工程师们实现快速打样的首选方案。但许多开发者在下单过程…

作者头像 李华