在 2021 年 2 月份基于 Keycloak 7 实现了一个关注微信公众号即登录的插件,在当年 9 月份收到咨询说在最新版 Keycloak 中不能使用了。于是做了一个升级,当时是升级到了 Keycloak 15,详见:
https://zhuanlan.zhihu.com/p/407932327

后来,又将 Keycloak 升级到了 16,发现插件不用做任何修改,也能适配使用。

但是时间又过去了一整年,Keycloak 又出了新版本,而且改动特别大,本文记录一下在适配 Keycloak 18 时需要做的一些改动,以供更多网友参考。

为什么再次升级?

其实也是在知乎上收到了咨询,才了解到 Keycloak 升级到 18 后,自定义的身份提供程序,需要以新的方式集成进去才行。由于客户的代码并不是开源的,需要保密,所以这里以开源的 Keycloak 微信插件举例说明要做的适配。因为这个关注公众号即登录插件,本质上就是 Keycloak 的一种自定义社交登录身份提供程序,所以具有普遍性,并且和我帮助客户的程序做的改动是一样的。
image.png

建立测试环境

插件源代码

源代码见: https://github.com/Jeff-Tian/keycloak-services-social-weixin

现在了解到不同的 Keycloak 版本可能表现不一样,为了方便测试,现在在项目代码中加入了 Dockerfile 和 docker-compose.yml 文件。这样可以随时切换不同的 Keycloak 版本。

Dockerfile

比如要验证 Keycloak 18,可以建立如下的 Dockerfile:

dockerfile FROM quay.io/keycloak/keycloak:18.0.2

COPY target/keycloak-services-social-weixin-0.1.1.jar /opt/keycloak/providers/

CMD [start-dev, --hostname-strict=false]

这里也展示了要适配 Keycloak 18,不用再像之前单独拷贝配置的 html 模板文件了。

docker-compose 文件

直接使用 docker run ... 的命令可以运行指定的 Keycloak 实例,但是要传递很多参数,还是有些不方便。如果能将需要的参数写在文件里就好了。其实这可以建立一个 docker-compose.yml 文件,从而每次要运行时,只需要执行 docker compose up 就可以了。这样的 docker-compose.yml 文件如下:

yaml version: 3

services: keycloak: build: context: . dockerfile: Dockerfile environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin ports: - 8080:8080 command: - start-dev

当然,如果你修改了 Dockerfile,需要在 docker compose up 之前,运行一下 docker compose build 。

如果同时要验证多个版本的 Keycloak,可以建立多个 Dockerfile 和 docker-compose.yml。比如再建立一个 Dockerfile.19,以及 docker-compose.19.yml,并在该 yml 文件中指向 Dockerfile.19 这个文件。那么,当想启动 Keycloak 19 时,只需要 docker compose -f docker-compose.19.yml up 即可。

pom 文件改动

要适配 Keycloak 18,先需要在 pom 文件中把对 Keycloak 的依赖版本做个修改,如下:

diff 4.0.0 org.keycloak keycloak-services-social-weixin

  • 0.0.66
  • 0.1.0

Keycloak Services Social WeiXin <maven.compiler.target>11</maven.compiler.target> <maven.compiler.source>11</maven.compiler.source>

  •   <keycloak.version>15.0.2</keycloak.version>
    
  •   <keycloak.version>18.0.2</keycloak.version>
    

模板文件的位置改动

按照之前的方式,模板文件会拷贝到 /opt/keycloak/themes/base/admin/resources/partials/realm-identity-provider-xxxx.html 这个位置,但是在 Keycloak 18 中,如果拷贝到这里,会导致 Admin Console 中出现资源找不到的错误。

image.png

对应的服务器端日志是找不到 index.ftl 模板文件:

image.png

看了一下 Keycloak 18.0.2 的文档,原来主题资源有专门的文件夹了,是在 theme-resources/ 之下,虽然带来了破坏性的改动,但是的确让工程变得更加紧凑了。正如之前建立测试环境时提到的,以后要添加自定义的社交登录插件,只需要拷贝一个 jar 文件就行了,而不用再单独去拷贝模板文件,因为模板文件通过 theme-resources 打包在 jar 文件中了。

image.png

具体来说,对于之前的配置界面模板,需要放置在项目的 resources/theme-resources/resources/partials 目录之下,比如,对于微信插件,就是:src/main/resources/theme-resources/resources/partials/realm-identity-provider-weixin-ext.html,迁移示例图如下:

image.png

Dockferfile 简化

如同之前提到的,可以删除拷贝模板文件的代码了,只保留 jar 文件的拷贝即可。同时留意所有带 jboss 路径的目录,需要删除 jboss。因为 Keycloak 18 不再基于 jboss。

diff COPY idps/wechat-mobile/keycloak-services-social-weixin.jar

  • /opt/jboss/keycloak/providers/
  • /opt/keycloak/providers/
  • COPY idps/wechat-mobile/templates/realm-identity-provider-weixin-ext.html

  • /opt/jboss/keycloak/themes/base/admin/resources/partials

  • COPY idps/wechat-mobile/templates/realm-identity-provider-weixin.html

  • /opt/jboss/keycloak/themes/base/admin/resources/partials

Dockerfile 中只需要拷贝一个 jar 文件即可。但是在运行 Dockerfile 之前,要记得 mvn clean package以生成最新的 jar 文件以供 docker build 时拷贝。

验证效果

docker compose up 在本地启动 Keycloak 18.0.2,添加自定义身份提供程序,选择“微信”,出现配置界面,即之前的 404 的问题被解决了。
image.png

image.png

Keycloak 19

遗憾的是,上面的方法,对于 Keycloak 19 不适用。Keycloak 19 带来了更大的更新,看起来 Keycloak 抛弃了我曾经吐槽过的 angular js,而是用 React 新写了 Keycloak 2 主题。之前多数的插件模板都是基于 angular js 写的,所以肯定在新的界面上不适用了。但是即使将 Realm 设置中的主题设置回 Keycloak 1,在添加自定义身份认证程序时,仍然会出现 404 页面。
image.png

通过查看 GitHub 上相关的讨论,发现 Keycloak 开发小组对此问题还没有达成一致,对于如何升级此关注公众号即登录插件以适配 Keycloak 19,未来再研究和分享。