近日,多位企业级Java开发者在社区反馈,将应用服务器从Red Hat JBoss Enterprise Application Platform(EAP)7迁移至EAP 8后,Keycloak SAML适配器出现严重错误,抛出异常:keycloak.adapters.saml.jakarta.servlet.SamlFilter error。该错误导致基于SAML的单点登录(SSO)流程中断,影响生产环境下的用户认证。经多方排查,问题根源在于JBoss EAP 8引入的Jakarta EE 10规范变更,以及Keycloak适配器版本未及时适配所致。

迁移背景:从javax到jakarta的“硬性”切换

JBoss EAP 7基于Java EE 8标准,所有Servlet相关类均位于javax.servlet包下。而JBoss EAP 8则全面转向Jakarta EE 10规范,核心包名从javax.servlet变更为jakarta.servlet。这一底层变化看似微小,却对依赖旧命名空间的第三方库造成“灭顶之灾”。Keycloak作为开源身份与访问管理平台,其SAML适配器(keycloak-saml-adapter)在旧版本中编译时引用了javax.servlet接口,直接部署到EAP 8时,由于应用服务器不再提供javax.servlet类,类加载机制无法匹配,最终触发SamlFilter实例化失败。

错误现象:从日志到终端用户的连锁反应

据受影响的企业IT管理员描述,迁移后首次访问受SAML保护的资源时,EAP 8服务器日志出现如下堆栈片段:

Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletException
    at org.keycloak.adapters.saml.jakarta.servlet.SamlFilter.doFilter(SamlFilter.java:63)
    ...
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletException

尽管异常类名是“jakarta.servlet”,但实际缺失的却是javax.servlet类。这是因为Keycloak旧版适配器的代码内部虽已尝试向jakarta.servlet迁移(从包名jakarta.servlet可见),但其引入的传递依赖仍包含对旧包名的引用,导致部分二进制类在运行时无法被EAP 8的模块加载器找到。浏览器侧则直接返回HTTP 500错误,用户无法完成SAML断言验证,认证流程彻底中断。

根本原因:Keycloak适配器版本与EAP 8不匹配

红帽官方在JBoss EAP 8发布时已明确要求所有应用程序必须使用Jakarta EE 10兼容的库。Keycloak项目从21.0.0版本开始正式支持Jakarta命名空间,但许多企业仍在使用Keycloak 18.x或19.x系列的适配器,这些版本仅提供javax.servlet变体。更棘手的是,即便应用团队手动将keycloak-saml-adapter JAR替换为21.0.0以上版本,若同时包含其他强制依赖(如keycloak-commonkeycloak-core),仍可能因版本不一致导致运行时冲突。

解决方案:三步走消除兼容性隐患

针对该问题,红帽专家与Keycloak社区给出了以下推荐方案:

  1. 升级Keycloak适配器至兼容版本:将keycloak-saml-adapter及相关依赖统一升级至22.0.0或更高版本。这些版本完全基于Jakarta EE 10编译,包名已彻底从javax.servlet迁移至jakarta.servlet。需注意同时更新keycloak-deploymentkeycloak-saml-core等配套JAR。

  2. 清理旧的模块覆盖(Module Override):若此前在EAP 7中通过modules目录覆盖了Keycloak适配器,迁移到EAP 8后必须删除或重建这些模块定义。建议使用红帽提供的JBoss EAP patch工具统一管理第三方库依赖。

  3. 使用Jakarta EE模式的部署描述符:检查web.xmljboss-web.xml等配置文件,确保所有过滤器类名引用指向jakarta.servlet包路径,而非旧版javax.servlet

此外,对于无法立即升级Keycloak版本的企业,可临时在EAP 8中启用“javax兼容”模块(通过--server-config=...参数加入javax.servlet.api,但红帽警告此做法仅作为短期桥接,存在安全风险且不官方支持。

行业影响与最佳实践建议

本次迁移问题并非个案。随着Jakarta EE 10在2023年底被广泛采用,大量依赖Servlet API的中间件(如Spring Security过滤器、Apache Shiro等)均面临相同挑战。企业IT团队在规划EAP 8迁移时,应提前对所有第三方库进行“Jakarta兼容性”检查:

  • 使用mvn dependency:tree工具查看依赖是否存在javax.servlet引用。
  • 优先选用已发布Jakarta命名的版本(如*-jakartae*-ee10后缀)。
  • 在测试环境中进行全链路SAML、OIDC流程回归测试。

截至发稿,Keycloak项目维护者表示,下一版本(23.x)将进一步简化适配器配置,自动检测运行时环境并切换命名空间。对于已受影响的生产环境,建议按照上述方案立即修复,以避免造成更大规模的认证中断。