所有 KeyCloak Admin API 调用出现 NullPointerException
NullPointerException on all KeyCloak Admin API Calls
我正在尝试使用 Java 客户端调用 KeyCloak Admin API。无论我尝试哪种操作——创建领域、创建用户帐户等——我都会收到以下异常:
javax.ws.rs.ProcessingException: java.lang.NullPointerException at
org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:53)
at
org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:573)
at
org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:438)
at
org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:102)
at
org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
at com.sun.proxy.$Proxy214.create(Unknown Source)
我的 KeyCloak 代码如下所示...
Keycloak kc = KeycloakBuilder.builder().realm("master").clientId("admin-cli").username("admin") .password("password").serverUrl("http://localhost:8880/auth")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();
RealmRepresentation realm = new RealmRepresentation();
realm.setDisplayName(displayName);
realm.setDisplayNameHtml(displayName);
realm.setRealm(realmName);
realm.setEnabled(enabled);
kc.realms().create(realm);
此时我看到了异常。关于这里可能出什么问题的任何想法?我看到针对管理员 API 的所有操作的异常。我知道数据可用,因为我可以对管理员进行 curl 调用 API 并且它工作正常。
curl -vki -H "Authorization: Bearer XXXXX" http://localhost:8880/auth/admin/realms/master
当我进行此调用时,我看到了预期的结果。我只在使用 Java 客户端时失败。知道这里发生了什么吗??
更新
我增加了我的 KeyCloak 实例上的调试日志。我在尝试创建安全领域后看到以下消息。 (注意:无论我执行什么操作,我都会看到类似的错误)
14:36:16,553 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) new JtaTransactionWrapper
14:36:16,553 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) was existing? false
14:36:16,557 DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-24) AUTHENTICATE CLIENT
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) client authenticator: client-secret
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) client authenticator SUCCESS: client-secret
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) Client admin-cli authenticated by client-secret
14:36:16,558 DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-24) AUTHENTICATE ONLY
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) processFlow
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-username requirement: REQUIRED
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-username
14:36:16,560 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-username
14:36:16,560 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator SUCCESS: direct-grant-validate-username
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-password requirement: REQUIRED
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-password
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-password
14:36:16,658 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator SUCCESS: direct-grant-validate-password
14:36:16,658 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-otp requirement: OPTIONAL
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-otp
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-otp
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator ATTEMPTED: direct-grant-validate-otp
14:36:16,661 DEBUG [org.keycloak.services.managers.AuthenticationSessionManager] (default task-24) Removing authSession 'df66e278-8ffe-47ab-84d1-36ffe9152021'. Expire restart cookie: true
14:36:16,673 DEBUG [org.keycloak.events] (default task-24) type=LOGIN, realmId=master, clientId=admin-cli, userId=c830af10-3cfd-4ce0-b1aa-83a857a290d7, ipAddress=172.18.0.1, auth_method=openid-connect, token_id=8876c7ad-3ea4-4356-8fc2-f9b50112b952, grant_type=password, refresh_token_type=Refresh, scope='profile email', refresh_token_id=4c2325fc-0bb5-40d9-af55-4985546fd39a, client_auth_method=client-secret, username=kcadmin
14:36:16,673 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) JtaTransactionWrapper commit
14:36:16,676 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) JtaTransactionWrapper end
更新 2
这个问题似乎与 运行在 Java EE 容器中使用此代码有关。如果我 运行 在独立 class 中完全相同的代码,它可以正常工作。但是,如果我将代码复制并粘贴到 servlet 并尝试 运行 它,我会收到 NullPointerException
。当我遇到问题时,我正在 运行 宁 Wildfly 13 上的代码。当通过 Arquillian 运行ning 集成测试时,我也看到了这个问题。我的假设是它一定与依赖关系有关,但我不知道需要更改什么。
您没有授权header。请尝试
Keycloak kc = KeycloakBuilder.builder().realm("master").clientId("admin-cli").username("admin") .password("password").authorization("authorization").serverUrl("http://localhost:8880/auth")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();
注意
.authorization("authorization")
解决了!!显然,我的 Wildfly 13.0 实例配置为启用 Java EE 8 支持。这似乎是问题的根本原因,因为删除该标志使所有测试用例都能按预期工作。不确定为什么这是个问题,但这绝对是根本问题。
如果您想保留 Java EE 8 对 WildFly 13 的支持,只需创建空的 jackson 提供程序:
public class CustomJacksonProvider extends ResteasyJackson2Provider {
}
并使用 ResteasyClientBuilder
的 register()
方法将其添加到您的 KeyCloak 构建器中:
Keycloak kc = KeycloakBuilder.builder()
.realm("master")
.clientId("admin-cli")
.username("admin")
.password("password")
.serverUrl("http://localhost:8880/auth")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).register(new CustomJacksonProvider()).build())
.build();
您还需要添加一些 resteasy 依赖项(如 scope=provided
)以便能够使用 ResteasyClientBuilder
和 ResteasyClientBuilder
:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.6.2.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>3.6.2.Final</version>
<scope>provided</scope>
</dependency>
简单地说(甚至可能太多),有一个与 Resteasy 库相关的错误,其中 JsonBindingProvider
优先于 ResteasyJackson2Provider
,这使得 [=20] 中的一些属性=] 有效载荷没有正确映射,它们的值丢失了。因此 NullPointerException。
如果您使用 JBoss 或 WildFly,最简单的解决方案应该是从 jboss-deployment-structure.xml
文件中的部署中排除 resteasy-json-binding-provider
模块:
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.jboss.resteasy.resteasy-json-binding-provider"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
我正在尝试使用 Java 客户端调用 KeyCloak Admin API。无论我尝试哪种操作——创建领域、创建用户帐户等——我都会收到以下异常:
javax.ws.rs.ProcessingException: java.lang.NullPointerException at org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:53) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:573) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:438) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:102) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) at com.sun.proxy.$Proxy214.create(Unknown Source)
我的 KeyCloak 代码如下所示...
Keycloak kc = KeycloakBuilder.builder().realm("master").clientId("admin-cli").username("admin") .password("password").serverUrl("http://localhost:8880/auth")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();
RealmRepresentation realm = new RealmRepresentation();
realm.setDisplayName(displayName);
realm.setDisplayNameHtml(displayName);
realm.setRealm(realmName);
realm.setEnabled(enabled);
kc.realms().create(realm);
此时我看到了异常。关于这里可能出什么问题的任何想法?我看到针对管理员 API 的所有操作的异常。我知道数据可用,因为我可以对管理员进行 curl 调用 API 并且它工作正常。
curl -vki -H "Authorization: Bearer XXXXX" http://localhost:8880/auth/admin/realms/master
当我进行此调用时,我看到了预期的结果。我只在使用 Java 客户端时失败。知道这里发生了什么吗??
更新
我增加了我的 KeyCloak 实例上的调试日志。我在尝试创建安全领域后看到以下消息。 (注意:无论我执行什么操作,我都会看到类似的错误)
14:36:16,553 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) new JtaTransactionWrapper
14:36:16,553 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) was existing? false
14:36:16,557 DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-24) AUTHENTICATE CLIENT
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) client authenticator: client-secret
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) client authenticator SUCCESS: client-secret
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) Client admin-cli authenticated by client-secret
14:36:16,558 DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-24) AUTHENTICATE ONLY
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) processFlow
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-username requirement: REQUIRED
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-username
14:36:16,560 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-username
14:36:16,560 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator SUCCESS: direct-grant-validate-username
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-password requirement: REQUIRED
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-password
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-password
14:36:16,658 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator SUCCESS: direct-grant-validate-password
14:36:16,658 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-otp requirement: OPTIONAL
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-otp
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-otp
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator ATTEMPTED: direct-grant-validate-otp
14:36:16,661 DEBUG [org.keycloak.services.managers.AuthenticationSessionManager] (default task-24) Removing authSession 'df66e278-8ffe-47ab-84d1-36ffe9152021'. Expire restart cookie: true
14:36:16,673 DEBUG [org.keycloak.events] (default task-24) type=LOGIN, realmId=master, clientId=admin-cli, userId=c830af10-3cfd-4ce0-b1aa-83a857a290d7, ipAddress=172.18.0.1, auth_method=openid-connect, token_id=8876c7ad-3ea4-4356-8fc2-f9b50112b952, grant_type=password, refresh_token_type=Refresh, scope='profile email', refresh_token_id=4c2325fc-0bb5-40d9-af55-4985546fd39a, client_auth_method=client-secret, username=kcadmin
14:36:16,673 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) JtaTransactionWrapper commit
14:36:16,676 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) JtaTransactionWrapper end
更新 2
这个问题似乎与 运行在 Java EE 容器中使用此代码有关。如果我 运行 在独立 class 中完全相同的代码,它可以正常工作。但是,如果我将代码复制并粘贴到 servlet 并尝试 运行 它,我会收到 NullPointerException
。当我遇到问题时,我正在 运行 宁 Wildfly 13 上的代码。当通过 Arquillian 运行ning 集成测试时,我也看到了这个问题。我的假设是它一定与依赖关系有关,但我不知道需要更改什么。
您没有授权header。请尝试
Keycloak kc = KeycloakBuilder.builder().realm("master").clientId("admin-cli").username("admin") .password("password").authorization("authorization").serverUrl("http://localhost:8880/auth")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();
注意
.authorization("authorization")
解决了!!显然,我的 Wildfly 13.0 实例配置为启用 Java EE 8 支持。这似乎是问题的根本原因,因为删除该标志使所有测试用例都能按预期工作。不确定为什么这是个问题,但这绝对是根本问题。
如果您想保留 Java EE 8 对 WildFly 13 的支持,只需创建空的 jackson 提供程序:
public class CustomJacksonProvider extends ResteasyJackson2Provider {
}
并使用 ResteasyClientBuilder
的 register()
方法将其添加到您的 KeyCloak 构建器中:
Keycloak kc = KeycloakBuilder.builder()
.realm("master")
.clientId("admin-cli")
.username("admin")
.password("password")
.serverUrl("http://localhost:8880/auth")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).register(new CustomJacksonProvider()).build())
.build();
您还需要添加一些 resteasy 依赖项(如 scope=provided
)以便能够使用 ResteasyClientBuilder
和 ResteasyClientBuilder
:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.6.2.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>3.6.2.Final</version>
<scope>provided</scope>
</dependency>
简单地说(甚至可能太多),有一个与 Resteasy 库相关的错误,其中 JsonBindingProvider
优先于 ResteasyJackson2Provider
,这使得 [=20] 中的一些属性=] 有效载荷没有正确映射,它们的值丢失了。因此 NullPointerException。
如果您使用 JBoss 或 WildFly,最简单的解决方案应该是从 jboss-deployment-structure.xml
文件中的部署中排除 resteasy-json-binding-provider
模块:
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.jboss.resteasy.resteasy-json-binding-provider"/>
</exclusions>
</deployment>
</jboss-deployment-structure>