无法使用 Keycloak 评估基于 Javascript 的策略

Posted

技术标签:

【中文标题】无法使用 Keycloak 评估基于 Javascript 的策略【英文标题】:Can't evaluate Javascript based policy with Keycloak 【发布时间】:2021-12-31 12:53:09 【问题描述】:

我正在尝试测试此项目 https://github.com/mposolda/devconf2019-authz/blob/master/cars-realm.json#L191 中定义的基于 javascript 的策略,但每次我尝试访问受保护的资源时,我都会在 keycloak 日志中收到以下错误:

Caused by: java.lang.IllegalStateException: Could not find ScriptEngine for script: Scriptid='null', realmId='cars', name='Only From a Specific Client Address', type='text/javascript', code='var contextAttributes = $evaluation.getContext().getAttributes();

if (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1')) 
    $evaluation.grant();
', description='Defines that only clients from a specific address can do something'
        at org.keycloak.keycloak-services@15.0.2//org.keycloak.scripting.DefaultScriptingProvider.createPreparedScriptEngine(DefaultScriptingProvider.java:106)
        at org.keycloak.keycloak-services@15.0.2//org.keycloak.scripting.DefaultScriptingProvider.prepareEvaluatableScript(DefaultScriptingProvider.java:72)
        at org.keycloak.keycloak-services@15.0.2//org.keycloak.scripting.DefaultScriptingProvider.prepareEvaluatableScript(DefaultScriptingProvider.java:33)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.js.JSPolicyProviderFactory.lambda$getEvaluatableScript$0(JSPolicyProviderFactory.java:109)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.js.ScriptCache.lambda$computeIfAbsent$0(ScriptCache.java:80)
        at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1224)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.js.ScriptCache.computeIfAbsent(ScriptCache.java:80)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.js.JSPolicyProviderFactory.getEvaluatableScript(JSPolicyProviderFactory.java:106)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.js.JSPolicyProvider.evaluate(JSPolicyProvider.java:46)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.aggregated.AggregatePolicyProvider.evaluate(AggregatePolicyProvider.java:66)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.aggregated.AggregatePolicyProvider.evaluate(AggregatePolicyProvider.java:66)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.permission.AbstractPermissionProvider.evaluate(AbstractPermissionProvider.java:56)
        at org.keycloak.keycloak-authz-policy-common@15.0.2//org.keycloak.authorization.policy.provider.permission.ScopePolicyProvider.evaluate(ScopePolicyProvider.java:52)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator.lambda$createPolicyEvaluator$0(DefaultPolicyEvaluator.java:116)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$PolicyCache.cacheQuery(StoreFactoryCacheSession.java:1098)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$PolicyCache.cacheQuery(StoreFactoryCacheSession.java:1073)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$PolicyCache.findByScopeIds(StoreFactoryCacheSession.java:1045)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.AuthorizationProvider$3.findByScopeIds(AuthorizationProvider.java:430)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator.evaluate(DefaultPolicyEvaluator.java:86)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.permission.evaluator.UnboundedPermissionEvaluator.lambda$evaluate$0(UnboundedPermissionEvaluator.java:49)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.permission.Permissions.lambda$all$1(Permissions.java:87)
        at java.base/java.util.function.Consumer.lambda$andThen$0(Consumer.java:65)
        at java.base/java.util.function.Consumer.lambda$andThen$0(Consumer.java:65)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$ResourceCache$1.accept(StoreFactoryCacheSession.java:678)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$ResourceCache$1.accept(StoreFactoryCacheSession.java:673)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
        at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
        at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.utils.ClosingStream.forEach(ClosingStream.java:128)
        at org.keycloak.keycloak-model-jpa@15.0.2//org.keycloak.authorization.jpa.store.JPAResourceStore.findByOwnerFilter(JPAResourceStore.java:136)
        at org.keycloak.keycloak-model-jpa@15.0.2//org.keycloak.authorization.jpa.store.JPAResourceStore.findByOwner(JPAResourceStore.java:101)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$ResourceCache.lambda$findByOwner$7(StoreFactoryCacheSession.java:673)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$ResourceCache.cacheQuery(StoreFactoryCacheSession.java:845)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$ResourceCache.cacheQuery(StoreFactoryCacheSession.java:830)
        at org.keycloak.keycloak-model-infinispan@15.0.2//org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheSession$ResourceCache.findByOwner(StoreFactoryCacheSession.java:671)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.AuthorizationProvider$4.findByOwner(AuthorizationProvider.java:501)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.permission.Permissions.all(Permissions.java:85)
        at org.keycloak.keycloak-server-spi-private@15.0.2//org.keycloak.authorization.permission.evaluator.UnboundedPermissionEvaluator.evaluate(UnboundedPermissionEvaluator.java:48)

为了使这个例子正常工作,我还需要做些什么吗?

Keycloak 版本:15.0.2 Java版本:15

谢谢!

【问题讨论】:

keycloak服务器使用什么版本的java?在 Java 15 中删除了 Rhino。如果服务器使用 Java 15+,这是预期的行为。如果是这种情况,那么我们可以降级到 Java this question。 我使用的是 Java 15,切换回 11 确实解决了问题!感谢您的帮助。 【参考方案1】:

当我们查看日志消息的第一行时:

Could not find ScriptEngine for script: Script ... type='text/javascript'... 

我们看到 keycloak 无法加载 javascript 脚本引擎。

由于 Java >= 15,JVM 没有提供任何 javascript 引擎(请参阅JEP 372)。这就是keycloak找不到javascript引擎的原因。

我看到了两种可能的解决方案:

通过一些 3rd 方库提供 javascript 引擎(详情请参阅 this question by Paul Taylor),或 将 Java 降级到

【讨论】:

以上是关于无法使用 Keycloak 评估基于 Javascript 的策略的主要内容,如果未能解决你的问题,请参考以下文章

Keycloak 问题无法在仅承载模式下交换代码以获得授权

在反向代理后面使用 Keycloak:无法打开管理员登录页面,因为内容混合

Keycloak修改注册数据

Spring base rest apis 的 Keycloak 安全性

使用 Keycloak 和 .NET 核心的基于角色的授权

Keycloak 无法使用有效令牌验证用户信息