【问题与需求】

接手一个现有的 SpringBoot 应用,其已实现了用户登录功能,并且拥有自己的数据库存储,登录的方式是“用户名+密码”。现在希望将用户认证的部分迁移到 Keycloak,但是让用户完全无感知。

也就是,继续使用原有的登录页面,用户继续输入原有的用户名和密码,但是 SpringBoot 服务不再做校验逻辑,而且委托给 Keycloak 完成。

【实施方案】

一、将旧系统中的用户名和密码导入到 Keycloak 中

本文将重点介绍第二步。第一步,我们假设可以拿到系统中的所有明文用户名及密码,并且数量不多,那么可以通过 Keycloak 的添加用户界面去完成用户的导入。
添加用户的链接: https://keycloak.jiwai.win/auth/admin/master/console/#/create/user/UniHeart
image.png

如果你现在知道更好的方式,欢迎留言告诉我。

二、将原有的登录校验功能改成调用 Keycloak 的 SPI 接口

建议先参考一下《 Free Arch: 如何在 Spring Boot 应用中集成 Keycloak? - Jeff Tian的文章 - 知乎 》,了解一些前提。

首先,需要在 Keycloak 中的相应 Realm 里配置一个客户端。

image.png

然后,找到登录需要用到的 SPI 接口

即 OIDC 的 token 接口,形如: https://keycloak.jiwai.win/auth/realms/UniHeart/protocol/openid-connect/token
这是从 Realm 的 well-known 接口中获取的:
image.png
比如,点击以上链接,打开的是 https://keycloak.jiwai.win/auth/realms/UniHeart/.well-known/openid-configuration,从返回的一系列自发现 url 中,就有这个 token 接口:
image.png

使用 Postman 手动调用测试

image.png
如上图所示,用这个接口可以成功登录。接下来,只需要在 SpringBoot 中,接收到用户名密码的部分,替换成以上对 Keycloak 的请求即可。这可以通过 Postman 的代码视图,选取 Java 即可。

这样做,可以只需要一个 Http 客户端,就完成了将用户认证转移到 Keycloak 的需求,不需要额外引入 Keycloak 相关的插件。

我在一个最简单的 SpringBoot 应用里,添加了以上代码,将获取到的用户名和密码,传入 Keycloak 的 token 接口,获取到了用户的访问令牌,以及身份令牌。完整的代码提交见: https://github.com/Jeff-Tian/keycloak-springboot/commit/b3bbe460589a76388243cf0413af4fdb0a06ed98
image.png

在线演示

如果你已经在我的 Keycloak 里有用户了(https://uniheart.pa-ca.me/keycloak/login),你可以使用你的用户名和密码,直接调用这个最简单的 SpringBoot 服务。为了保持简单,没有添加界面,所以用户名和密码是通过 url 参数传递的,完全可以模拟实际的 SpringBoot 效果。但是在真正的应用里,千万不要将用户名和密码通过 url 传递!
https://tranquil-plains-58233.herokuapp.com/[email protected]&password=xxxx

image.png

本地运行这个示例

参考 https://github.com/Jeff-Tian/keycloak-springboot 的 README, shell git clone https://github.com/Jeff-Tian/keycloak-springboot cd keycloak-springboot mvn clean install mvn spring-boot:run -f pom.xml

open http://localhost:8080/[email protected]&password=xxxx

结果如下:
image.png