
Keycloak 升级至 21.x 后,text/javascript 脚本因 Nashorn 引擎被移除而无法加载,导致 IllegalStateException: Could not find ScriptEngine 错误;需手动引入兼容的 Nashorn Core 实现并正确部署。
keycloak 升级至 21.x 后,javascript 脚本因 nashorn 引擎被移除而无法加载,导致 `illegalstateexception: could not find scriptengine` 错误;需手动引入兼容的 nashorn core 实现并正确部署。
自 Java 15 起,Nashorn JavaScript 引擎已被正式移除;而 Keycloak 21+(基于 Quarkus 构建)默认不再内置任何 ScriptEngine 实现,包括对 text/javascript MIME 类型的支持。这与 Keycloak 12(基于 WildFly + Java 8/11)中默认启用 Nashorn 的行为形成显著差异——因此迁移后原有脚本认证逻辑会直接失败,new ScriptEngineManager().getEngineByMimeType("text/javascript") 返回 null。
✅ 解决方案:集成 Nashorn Core
推荐使用 OpenJDK Nashorn Core 的独立实现(兼容 Java 11+),它不依赖 JVM 内置引擎,而是以纯 Java 库形式提供 ScriptEngine 支持。
1. 添加 Maven 依赖(构建时)
<dependencies><dependency><groupid>org.openjdk.nashorn</groupid><artifactid>nashorn-core</artifactid><version>15.4</version></dependency><!-- Nashorn 依赖 ASM,需一并引入 --><dependency><groupid>org.ow2.asm</groupid><artifactid>asm</artifactid><version>9.6</version></dependency><dependency><groupid>org.ow2.asm</groupid><artifactid>asm-util</artifactid><version>9.6</version></dependency><dependency><groupid>org.ow2.asm</groupid><artifactid>asm-commons</artifactid><version>9.6</version></dependency></dependencies>
⚠️ 注意:nashorn-core 15.4 是目前与 Keycloak 21+ 兼容性最佳的稳定版本;避免使用 16.0+(存在 API 不兼容风险)。
2. 构建并部署 Provider JAR
Keycloak 21+ 要求自定义脚本引擎必须以 Provider 插件 形式部署到 providers/ 目录:
<build><plugins><plugin><groupid>org.apache.maven.plugins</groupid><artifactid>maven-dependency-plugin</artifactid><executions><execution><id>copy-dependencies-quarkus</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputdirectory>${project.build.directory}/keycloak-server-extras/providers</outputdirectory><includeartifactids>nashorn-core,asm,asm-util,asm-commons</includeartifactids></configuration></execution></executions></plugin></plugins></build>
构建完成后,将生成的 JAR 文件复制到 Keycloak 服务器的 providers/ 目录(例如 Docker 部署中):
COPY providers/target/keycloak-server-extras/providers/* /opt/keycloak/providers/
重启 Keycloak 后,ScriptEngineManager 将能成功识别 text/javascript 并返回 Nashorn Core 实例。
? 验证方式
可在自定义 Authenticator 或调试日志中添加验证代码:
ScriptEngine engine = new ScriptEngineManager()
.getEngineByMimeType("text/javascript");
System.out.println("JS Engine found: " + (engine != null)); // 应输出 true
? 注意事项与替代建议
- 安全性提醒:Nashorn 已停止维护,生产环境建议尽快将脚本逻辑迁移到 Java-based Authenticators(如 UserSessionNoteAuthenticator)或使用 Keycloak 的新扩展机制(SPI)。
- 性能考量:Nashorn Core 是解释执行,性能弱于 GraalVM JS;若需高性能脚本支持,可评估 GraalVM Polyglot embedding(需额外适配 Keycloak SPI)。
- MIME 类型一致性:确保脚本资源的 mimeType 显式设为 "text/javascript"(而非 "application/javascript"),Keycloak 21 默认仅注册前者。
通过上述配置,即可无缝恢复 Keycloak 21+ 中基于 JavaScript 的脚本认证能力,保障平滑升级与业务连续性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











