
Keycloak 21 升级后因 Nashorn 引擎被移除,导致 text/javascript 脚本无法解析并抛出 IllegalStateException;需手动引入 nashorn-core 并正确部署至 providers 目录方可恢复脚本认证功能。
keycloak 21 升级后因 nashorn 引擎被移除,导致 `text/javascript` 脚本无法解析并抛出 `illegalstateexception`;需手动引入 `nashorn-core` 并正确部署至 providers 目录方可恢复脚本认证功能。
从 Keycloak 12 迁移到 21.0.1 后,基于 JavaScript 的自定义认证流程(如 ScriptBasedAuthenticator)普遍失败,核心错误为:
ScriptEngine engineByMimeType = new ScriptEngineManager().getEngineByMimeType("text/javascript");
// 返回 null → 触发 IllegalStateException: "Could not find ScriptEngine for script"这是因为:Java 15+ 已彻底移除内置的 Nashorn JavaScript 引擎(JEP 372),而 Keycloak 21 默认构建和运行在 Java 17+ 环境下(推荐 JDK 17/21),不再自动提供 text/javascript 对应的 ScriptEngine 实现。
✅ 正确解决方案是显式引入兼容的 Nashorn 替代实现 —— nashorn-core(OpenJDK 社区维护的独立分支),并确保其被 Keycloak 类加载器识别。
✅ 配置与部署步骤
1. 添加依赖(Maven)
在自定义 provider 模块的 pom.xml 中引入 nashorn-core 及必要 ASM 依赖(Nashorn 运行时所需):
立即学习“Java免费学习笔记(深入)”;
<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>2. 构建时复制到 Keycloak providers 目录
使用 maven-dependency-plugin 将依赖 JAR 自动拷贝至 Keycloak 的 providers/ 目录(Quarkus 模式下路径为 ${project.build.directory}/keycloak-server-extras/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>3. 部署至 Keycloak 实例
构建完成后,将生成的 JAR 文件(含 nashorn-core 等)复制到 Keycloak 服务端的 providers/ 目录:
# 示例(Docker 构建上下文) COPY providers/target/keycloak-server-extras/providers/* /opt/keycloak/providers/
⚠️ 注意:Keycloak 启动时会扫描 providers/ 下所有 JAR,并将其加入类路径。必须确保 nashorn-core.jar 在该目录中且未被排除或重命名。
4. 验证脚本引擎可用性(可选调试)
可在自定义 provider 中添加临时日志验证:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByMimeType("text/javascript");
System.out.println("JS Engine found: " + (engine != null)); // 应输出 true? 关键注意事项
- ❌ 不要尝试使用 --add-modules jdk.scripting.nashorn:该模块在 JDK 15+ 中已删除,参数无效;
- ✅ nashorn-core 15.4 兼容 JDK 11–21,是目前 Keycloak 官方文档推荐的方案;
- ? 若后续迁移到 GraalVM 或需更高性能,建议逐步将脚本逻辑重构为 Java SPI 实现,而非长期依赖 Nashorn;
- ? Keycloak 22+ 开始实验性支持 GraalVM JS(需额外配置),但截至 21.x,nashorn-core 仍是唯一稳定解。
完成上述配置后重启 Keycloak,原有 text/javascript 认证脚本即可正常加载与执行,IllegalStateException 将不再出现。


















