
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/ 目录:
立即学习“Java免费学习笔记(深入)”;
<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 的脚本认证能力,保障平滑升级与业务连续性。


















