0

0

Keycloak 自定义认证流程完整实现指南

花韻仙語

花韻仙語

发布时间:2026-02-09 15:07:43

|

101人浏览过

|

来源于php中文网

原创

Keycloak 自定义认证流程完整实现指南

本文详细讲解如何在 keycloak 中实现基于自定义字段(如 fielda、fieldb、hash)的 oauth 2.0 密码模式认证流程,替代默认的 username/password 验证,并完成 authenticator 与 authenticatorfactory 的注册、部署及流程绑定。

要在 Keycloak 中实现完全自定义的认证逻辑(例如接收 fieldA、fieldB 和 hash 作为凭证,而非标准 username/password),并使其兼容标准 OIDC Token 端点(如 POST /realms/{realm}/protocol/openid-connect/token?grant_type=password),仅实现 Authenticator 接口是不够的——你必须将其封装为可插拔的 SPI(Service Provider Interface)组件,并通过 Keycloak 管理控制台启用。以下是完整、可落地的操作流程:

✅ 第一步:实现核心认证逻辑(Authenticator)

你的 CustomAuthenticator 需从请求中提取自定义参数,并完成业务校验(如签名验证、令牌解密、第三方系统鉴权等)。注意:Keycloak 默认密码流要求用户已存在且处于启用状态,因此需确保 UserModel 被正确关联。

public class CustomAuthenticator implements Authenticator {

    @Override
    public void authenticate(AuthenticationFlowContext context) {
        // 1. 从表单请求中获取自定义字段(非 username/password)
        String fieldA = context.getHttpRequest().getDecodedFormParameters().getFirst("fieldA");
        String fieldB = context.getHttpRequest().getDecodedFormParameters().getFirst("fieldB");
        String hash = context.getHttpRequest().getDecodedFormParameters().getFirst("hash");

        // 2. 执行自定义校验逻辑(示例:简单哈希比对,生产环境请使用 HMAC/签名验签)
        if (isValidCredentials(fieldA, fieldB, hash)) {
            // 3. 根据 fieldA(或其它唯一标识)查找对应用户(注意:需确保该用户已在 Keycloak 中存在)
            UserModel user = context.getSession()
                    .users()
                    .getUserByUsername(fieldA, context.getRealm()); // 或用 getUserById / searchUsersByAttribute

            if (user != null && user.isEnabled()) {
                context.setUser(user);
                context.success(); // 认证成功 → 进入后续步骤(如角色映射、token 发放)
                return;
            }
        }

        // 认证失败:返回标准错误响应
        context.failure(AuthenticationFlowError.INVALID_USER);
    }

    private boolean isValidCredentials(String fieldA, String fieldB, String hash) {
        // ✅ 替换为实际业务逻辑:如调用内部服务、验证 JWT、校验 HMAC-SHA256 签名等
        return "expected-hash".equals(hash) && fieldA != null && fieldB != null;
    }

    @Override
    public void action(AuthenticationFlowContext context) {
        // 此方法用于处理表单提交后的 POST 操作(如二次确认),纯 API 流程中通常无需实现
        authenticate(context);
    }

    @Override
    public boolean requiresUser() {
        return true; // 表明此步骤需要关联一个用户(否则 context.setUser() 无效)
    }

    @Override
    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
        return true; // 简化处理;如需细粒度控制(如仅对某类用户启用),可在此校验
    }

    @Override
    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
        // 可选:设置强制操作(如首次登录修改密码)
    }

    @Override
    public void close() {
        // 资源清理(如关闭连接池),若无则留空
    }
}
⚠️ 关键注意事项:authenticate() 中必须调用 context.setUser(user) + context.success(),否则 Keycloak 不会颁发 token;用户必须预先存在于 Realm 中(可通过 Admin REST API、管理控制台或用户联合方式导入),Keycloak 不支持“动态创建用户+认证”一体化(除非额外实现 UserStorageProvider);若需无用户预置的场景(如手机号+短信验证码直登),应结合 UserStorageProvider 或改用 Direct Grant 流程扩展。

✅ 第二步:提供工厂类(AuthenticatorFactory)

AuthenticatorFactory 是 Keycloak 加载你认证器的入口,负责声明元信息并返回实例:

public class CustomAuthenticatorFactory implements AuthenticatorFactory {

    public static final String PROVIDER_ID = "custom-sso";

    private static final CustomAuthenticator SINGLETON = new CustomAuthenticator();

    @Override
    public String getDisplayType() {
        return "Custom SSO Flow"; // 控制台中显示的名称
    }

    @Override
    public String getReferenceCategory() {
        return "custom-auth"; // 分组标识(可选)
    }

    @Override
    public boolean isConfigurable() {
        return false; // 如无需运行时配置,设为 false
    }

    @Override
    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
        return new AuthenticationExecutionModel.Requirement[]{
                AuthenticationExecutionModel.Requirement.REQUIRED,
                AuthenticationExecutionModel.Requirement.DISABLED
        };
    }

    @Override
    public Authenticator create(KeycloakSession session) {
        return SINGLETON;
    }

    @Override
    public String getId() {
        return PROVIDER_ID;
    }

    @Override
    public String getHelpText() {
        return "Authenticates users via custom fieldA/fieldB/hash credentials.";
    }
}

✅ 第三步:注册 SPI 服务

在项目资源目录下创建文件:
src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory

文件内容仅一行(指向你的 Factory 实现类):

PowerLib图书馆门户小程序
PowerLib图书馆门户小程序

前后端完整代码包括本馆动态,新书来了,书籍榜单,服务指南,进馆预约,活动讲座预约等功能,采用腾讯提供的小程序云开发解决方案,无须服务器和域名 预约管理:开始/截止时间/人数均可灵活设置,可以自定义客户预约填写的数据项 预约凭证:支持线下到场后校验签到/核销/二维码自助签到等多种方式详尽的 预约数据:支持预约名单数据导出Excel,打印

下载
com.example.auth.CustomAuthenticatorFactory

? 提示:确保构建后该文件存在于 JAR 包的 META-INF/services/ 路径下。

✅ 第四步:打包部署与流程绑定

  1. 将模块打包为 JAR(推荐使用 Maven Shade Plugin 合并依赖);
  2. 将 JAR 放入 Keycloak 的 providers/ 目录(如 $KEYCLOAK_HOME/providers/);
  3. 重启 Keycloak(或执行 bin/kc.sh build --features=preview + kc.sh start,取决于版本);
  4. 登录管理控制台 → Realm Settings → Authentication → Flows
  5. 复制内置 Direct Grant 流程(因 Browser 流不支持密码模式,而 Direct Grant 才是 /token?grant_type=password 的实际载体);
  6. 在新流程中,点击 + Execution → 选择你的 Custom SSO Flow → 设为 REQUIRED;
  7. 返回 Authentication → Bindings,将 Direct Grant Flow 绑定到你新建的自定义流程。

✅ 最终验证(cURL 示例)

curl -X POST \
  "http://localhost:8080/realms/myrealm/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=myclient" \
  -d "client_secret=xxx" \
  -d "grant_type=password" \
  -d "fieldA=user123" \
  -d "fieldB=serviceX" \
  -d "hash=abc123def456"

✅ 成功时将返回标准 OIDC token 响应(含 access_token, refresh_token, expires_in)。

? 总结

  • Keycloak 自定义认证 ≠ 仅写一个 Authenticator,而是完整的 SPI 插件开发流程
  • 必须配套 AuthenticatorFactory + META-INF/services 注册 + 控制台流程绑定;
  • Direct Grant 流程是密码模式的载体,不可修改内置 Browser 流;
  • 用户必须预先存在,认证器只负责“验证身份”,不负责“创建身份”;
  • 生产环境务必强化安全校验(防重放、签名时效、密钥轮转、审计日志)。

遵循以上步骤,即可安全、稳定地将 Keycloak 集成至任意自有认证体系,实现真正的协议兼容与业务解耦。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Java Maven专题
Java Maven专题

本专题聚焦 Java 主流构建工具 Maven 的学习与应用,系统讲解项目结构、依赖管理、插件使用、生命周期与多模块项目配置。通过企业管理系统、Web 应用与微服务项目实战,帮助学员全面掌握 Maven 在 Java 项目构建与团队协作中的核心技能。

0

2025.09.15

curl_exec
curl_exec

curl_exec函数是PHP cURL函数列表中的一种,它的功能是执行一个cURL会话。给大家总结了一下php curl_exec函数的一些用法实例,这个函数应该在初始化一个cURL会话并且全部的选项都被设置后被调用。他的返回值成功时返回TRUE, 或者在失败时返回FALSE。

450

2023.06.14

linux常见下载安装工具
linux常见下载安装工具

linux常见下载安装工具有APT、YUM、DNF、Snapcraft、Flatpak、AppImage、Wget、Curl等。想了解更多linux常见下载安装工具相关内容,可以阅读本专题下面的文章。

179

2023.10.30

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6352

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

830

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1077

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

1495

2024.03.01

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1344

2023.10.19

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

130

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.9万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号