【问题与需求】
接手一个现有的 SpringBoot 应用,其已实现了用户登录功能,并且拥有自己的数据库存储,登录的方式是“用户名+密码”。现在希望将用户认证的部分迁移到 Keycloak,但是让用户完全无感知。
也就是,继续使用原有的登录页面,用户继续输入原有的用户名和密码,但是 SpringBoot 服务不再做校验逻辑,而且委托给 Keycloak 完成。
【实施方案】
一、将旧系统中的用户名和密码导入到 Keycloak 中
本文将重点介绍第二步。第一步,我们假设可以拿到系统中的所有明文用户名及密码,并且数量不多,那么可以通过 Keycloak 的添加用户界面去完成用户的导入。
添加用户的链接: https://keycloak.jiwai.win/auth/admin/master/console/#/create/user/UniHeart
如果你现在知道更好的方式,欢迎留言告诉我。
二、将原有的登录校验功能改成调用 Keycloak 的 SPI 接口
建议先参考一下《 Free Arch: 如何在 Spring Boot 应用中集成 Keycloak? - Jeff Tian的文章 - 知乎 》,了解一些前提。
首先,需要在 Keycloak 中的相应 Realm 里配置一个客户端。
然后,找到登录需要用到的 SPI 接口
即 OIDC 的 token 接口,形如: https://keycloak.jiwai.win/auth/realms/UniHeart/protocol/openid-connect/token。
这是从 Realm 的 well-known 接口中获取的:
比如,点击以上链接,打开的是 https://keycloak.jiwai.win/auth/realms/UniHeart/.well-known/openid-configuration,从返回的一系列自发现 url 中,就有这个 token 接口:
使用 Postman 手动调用测试
如上图所示,用这个接口可以成功登录。接下来,只需要在 SpringBoot 中,接收到用户名密码的部分,替换成以上对 Keycloak 的请求即可。这可以通过 Postman 的代码视图,选取 Java 即可。
这样做,可以只需要一个 Http 客户端,就完成了将用户认证转移到 Keycloak 的需求,不需要额外引入 Keycloak 相关的插件。
我在一个最简单的 SpringBoot 应用里,添加了以上代码,将获取到的用户名和密码,传入 Keycloak 的 token 接口,获取到了用户的访问令牌,以及身份令牌。完整的代码提交见: https://github.com/Jeff-Tian/keycloak-springboot/commit/b3bbe460589a76388243cf0413af4fdb0a06ed98
在线演示
如果你已经在我的 Keycloak 里有用户了(https://uniheart.pa-ca.me/keycloak/login),你可以使用你的用户名和密码,直接调用这个最简单的 SpringBoot 服务。为了保持简单,没有添加界面,所以用户名和密码是通过 url 参数传递的,完全可以模拟实际的 SpringBoot 效果。但是在真正的应用里,千万不要将用户名和密码通过 url 传递!
https://tranquil-plains-58233.herokuapp.com/login-by-user[email protected]&password=xxxx
本地运行这个示例
参考 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/login-by-use[email protected]&password=xxxx