找不到 Keycloak 提供程序

Keycloak Provider not found

我有一个 Keycloak 4.2.1 服务器,我正在尝试为其实现自定义 "LoginFormsProvider"。我的目标是使用附加组件扩展到登录页面 (freemarker),在我的例子中是一个简单的信息框。我想在 Provider class.

中设置的那个框的内容

我已经实现了另外两个自定义提供程序,它们工作正常(UserStorageProvider 和 EventListenerProvider)。所以我的.jar文件被服务器找到了。

但我对 "LoginFormsProvider" 有疑问。服务器未找到提供者。请参阅下面的堆栈跟踪...

我在 "META-INF/services" 路径中添加了一个文件 "org.keycloak.login.LoginFormsProviderFactory" 带有包和 class 名称,"de.test.login.TestLoginFactory"(不带引号)。

这导致了我的提供商的工厂 Class。 就像我为其他提供商所做的那样。

我的工厂Class 看起来像这样:

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;
    }

}

这里是提供商 class:

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="[&quot;REFRESH_TOKEN&quot;]"/>
                </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>
...

现在,当我启动服务器时,我得到了下面的堆栈跟踪。我不知道他为什么找不到工厂 class?

我检查了.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.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.call(DeploymentManagerImpl.java:565)
    at io.undertow.servlet.core.DeploymentManagerImpl.call(DeploymentManagerImpl.java:536)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call(ServletRequestContextThreadSetupAction.java:42)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction.call(ContextClassLoaderSetupAction.java:43)
    at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create[=14=](SecurityContextThreadSetupAction.java:105)
    at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction$$Lambda7/1223919585.call(Unknown Source)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=14=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda8/1436296213.call(Unknown Source)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=14=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda8/1436296213.call(Unknown Source)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=14=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda8/1436296213.call(Unknown Source)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=14=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction$$Lambda8/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.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
</pre> 

如果你们需要更多信息,请告诉我。

我是不是忘记了什么或者有什么错误?

非常感谢你的帮助。

亲切的问候

你用的是什么版本的keycloak?如果它是较新版本之一(1.x 以上),那么您似乎在 类 中使用了 "wrong" 导入语句。

请尝试更新所有必要的依赖项,看看是否可行。