java - 未找到 Keycloak 提供程序
问题描述
我有一个 Keycloak 4.2.1 服务器,我试图为它实现一个自定义的“LoginFormsProvider”。我的目标是使用附加组件(在我的例子中是一个简单的信息框)扩展到登录页面(freemarker)。我想在 Provider 类中设置该框的内容。
我已经实现了另外两个自定义提供程序,它们工作正常(UserStorageProvider 和 EventListenerProvider)。所以我的 .jar 文件被服务器找到了。
但我对“LoginFormsProvider”有疑问。服务器找不到提供程序。请参阅下面的堆栈跟踪...
我在“META-INF/services”路径中添加了一个文件“org.keycloak.login.LoginFormsProviderFactory”,其包和类名称为“de.test.login.TestLoginFactory”(不带引号)。
这导致我的提供者的工厂类。就像我为其他提供商所做的那样。
我的 FactoryClass 看起来像这样:
package de.test.login;
import java.util.LinkedHashMap;
import java.util.Map;
import org.jboss.logging.Logger;
import org.keycloak.Config.Scope;
import org.keycloak.freemarker.FreeMarkerUtil;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.login.LoginFormsProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ServerInfoAwareProviderFactory;
public class TestLoginFactory implements LoginFormsProviderFactory{
private FreeMarkerUtil freeMarker;
private final static String PROVIDER = "test-login-provider";
@Override
public LoginFormsProvider create(KeycloakSession session) {
return new TestLoginProvider(session, freeMarker);
}
@Override
public void init(Scope config) {
freeMarker = new FreeMarkerUtil();
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
freeMarker = null;
}
@Override
public String getId() {
return PROVIDER;
}
}
这里提供者类:
package de.test.login;
import javax.ws.rs.core.Response;
import org.jboss.logging.Logger;
import org.keycloak.freemarker.FreeMarkerUtil;
import org.keycloak.login.freemarker.FreeMarkerLoginFormsProvider;
import org.keycloak.models.KeycloakSession;
public class TestLoginProvider extends FreeMarkerLoginFormsProvider{
final private Logger logger = Logger.getLogger(this.getClass());
public TestLoginProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
super(session, freeMarker);
}
@Override
public Response createLogin(){
logger.info("do crazy stuff");
Response response = super.createLogin();
return response;
}
}
在我的standalone.xml 中,我在其他 spi 声明附近添加了一个 spi 声明。
<spi name="login">
<default-provider>test-login-provider</default-provider>
</spi>
这里是standalone.xml的完整部分:
...
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
<web-context>auth</web-context>
<providers>
<provider>
classpath:${jboss.home.dir}/providers/*
</provider>
</providers>
<master-realm-name>master</master-realm-name>
<scheduled-task-interval>900</scheduled-task-interval>
<theme>
<staticMaxAge>2592000</staticMaxAge>
<cacheThemes>true</cacheThemes>
<cacheTemplates>true</cacheTemplates>
<dir>${jboss.home.dir}/themes</dir>
</theme>
<spi name="eventsStore">
<provider name="jpa" enabled="true">
<properties>
<property name="exclude-events" value="["REFRESH_TOKEN"]"/>
</properties>
</provider>
</spi>
<spi name="userCache">
<provider name="default" enabled="true"/>
</spi>
<spi name="userSessionPersister">
<default-provider>jpa</default-provider>
</spi>
<spi name="timer">
<default-provider>basic</default-provider>
</spi>
<spi name="login">
<default-provider>test-login-provider</default-provider>
</spi>
<spi name="connectionsHttpClient">
<provider name="default" enabled="true"/>
</spi>
<spi name="connectionsJpa">
<provider name="default" enabled="true">
<properties>
<property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>
<property name="initializeEmpty" value="true"/>
<property name="migrationStrategy" value="update"/>
<property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
</properties>
</provider>
</spi>
<spi name="realmCache">
<provider name="default" enabled="true"/>
</spi>
<spi name="connectionsInfinispan">
<default-provider>default</default-provider>
<provider name="default" enabled="true">
<properties>
<property name="cacheContainer" value="java:comp/env/infinispan/Keycloak"/>
</properties>
</provider>
</spi>
<spi name="jta-lookup">
<default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>
<provider name="jboss" enabled="true"/>
</spi>
<spi name="publicKeyStorage">
<provider name="infinispan" enabled="true">
<properties>
<property name="minTimeBetweenRequests" value="10"/>
</properties>
</provider>
</spi>
<spi name="x509cert-lookup">
<default-provider>${keycloak.x509cert.lookup.provider:default}</default-provider>
<provider name="default" enabled="true"/>
</spi>
</subsystem>
...
现在,当我启动服务器时,我得到了下面的堆栈跟踪。我不知道他为什么找不到工厂类?
我检查了 .jar 文件,没有丢失任何文件。
堆栈跟踪:
08:54:32,971 INFO [org.jboss.as.server] (Thread-2) WFLYSRV0220: Server shutdown has been requested via an OS signal
08:54:32,973 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 49) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./auth: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./auth: java.lang.RuntimeException: RESTEASY003325: Failed to construct public org.keycloak.services.resources.KeycloakApplication(javax.servlet.ServletContext,org.jboss.resteasy.core.Dispatcher)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:84)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: java.lang.RuntimeException: RESTEASY003325: Failed to construct public org.keycloak.services.resources.KeycloakApplication(javax.servlet.ServletContext,org.jboss.resteasy.core.Dispatcher)
at org.jboss.resteasy.core.ConstructorInjectorImpl.construct(ConstructorInjectorImpl.java:162)
at org.jboss.resteasy.spi.ResteasyProviderFactory.createProviderInstance(ResteasyProviderFactory.java:2298)
at org.jboss.resteasy.spi.ResteasyDeployment.createApplication(ResteasyDeployment.java:340)
at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:253)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.init(ServletContainerDispatcher.java:120)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.init(HttpServletDispatcher.java:36)
at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)
at org.wildfly.extension.undertow.security.RunAsLifecycleInterceptor.init(RunAsLifecycleInterceptor.java:78)
at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:103)
at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:250)
at io.undertow.servlet.core.ManagedServlet.createServlet(ManagedServlet.java:133)
at io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:565)
at io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:536)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction$$Lambda$847/1223919585.call(Unknown Source)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda$848/1436296213.call(Unknown Source)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda$848/1436296213.call(Unknown Source)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda$848/1436296213.call(Unknown Source)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda$848/1436296213.call(Unknown Source)
at io.undertow.servlet.core.DeploymentManagerImpl.start(DeploymentManagerImpl.java:578)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:100)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:81)
... 6 more
Caused by: java.lang.RuntimeException: Failed to find provider test-login-provider for login
at org.keycloak.services.DefaultKeycloakSessionFactory.checkProvider(DefaultKeycloakSessionFactory.java:171)
at org.keycloak.services.DefaultKeycloakSessionFactory.init(DefaultKeycloakSessionFactory.java:90)
at org.keycloak.services.resources.KeycloakApplication.createSessionFactory(KeycloakApplication.java:326)
at org.keycloak.services.resources.KeycloakApplication.(KeycloakApplication.java:117)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.jboss.resteasy.core.ConstructorInjectorImpl.construct(ConstructorInjectorImpl.java:150)
... 33 more
如果你们需要更多信息,请告诉我。
我忘记了什么还是有什么错误?
我会非常感谢你的帮助。
亲切的问候
解决方案
你用什么版本的keycloak?如果它是更高版本之一(高于 1.x),那么您似乎在您的类中使用了“错误”的导入语句。
请尝试更新所有必要的依赖项,看看是否可行。
推荐阅读
- php - 使用 API 在 Shopify 中添加到购物车
- postgresql - Postgres中的工作日计数
- javascript - 在 React 中使用 useState 更新二维数组矩阵
- ruby-on-rails - ruby void 值表达式
- node.js - 如何跨多个 Node.js Lambda 函数共享配置
- angular - 离子科尔多瓦android构建问题
- c# - 无法从队列中移动 Instatiated Object,而是更改预制件的变换
- regex - 具有使用多个单词的搜索功能的 Google 表格自定义公式
- javascript - 如何使用 Angular 中的指令解决排序数字问题
- android-studio - SDK 工具更新后 Android AVD 运行失败且 HAXM 安装失败