部署自定义SPI(FreeMarkerLoginFormsProvider)时出现问题

时间:2019-06-19 08:36:52

标签: jboss keycloak

故事

我正在使用密钥斗篷6.0.1。我的领域涉及两种类型的用户:管理员和普通用户。我需要一个可以区分它们的主题,因为登录名是不同的(3个字段对2个字段)。因此,我想扩展提供程序FreeMarkerLoginFormsProvider来通过自定义参数。我正在使用keycloak部署程序来部署我的SPI。

问题

不幸的是,Keycloak在部署时引发异常:

  

09:55:32,170错误[org.jboss.as.controller.management-operation](DeploymentScanner-threads-1)WFLYCTL0013:操作(“ full-replace-deployment”)失败-地址:([])-故障描述:{“ WFLYCTL0080:失败的服务” => {“ jboss.deployment.unit。\” spi-1.0.0.jar \“。POST_MODULE” =>“ WFLYSRV0153:无法处理部署的阶段POST_MODULE \” spi- 1.0.0.jar \“      造成原因:java.lang.NoClassDefFoundError:org / keycloak / theme / FreeMarkerUtil      由以下原因引起:java.lang.ClassNotFoundException:服务模块加载程序的[Module \“ deployment.spi-1.0.0.jar \”中的org.keycloak.theme.FreeMarkerUtil   09:55:32,165错误[org.jboss.msc.service.fail](MSC服务线程1-3)MSC000001:无法启动服务jboss.deployment.unit。“ spi-1.0.0.jar”。POST_MODULE:org服务jboss.deployment.unit。“ spi-1.0.0.jar”中的.jboss.msc.service.StartException。POST_MODULE:WFLYSRV0153:无法处理部署“ spi-1.0.0.jar”的阶段POST_MODULE       在org.jboss.as.server@8.0.0.Final//org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:183)       在org.jboss.msc@1.4.5.Final//org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1738)       在org.jboss.msc@1.4.5.Final//org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1700)       在org.jboss.msc@1.4.5.Final//org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1558)       在org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)       在org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)       在org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)       在org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)       在java.base / java.lang.Thread.run(Thread.java:834)   造成原因:java.lang.NoClassDefFoundError:org / keycloak / theme / FreeMarkerUtil       在deployment.spi-1.0.0.jar // com.example.keycloak.spi.CustomFreeMarkerLoginFormsProviderFactory.init(CustomFreeMarkerLoginFormsProviderFactory.java:23)       在org.keycloak.keycloak-services@6.0.1//org.keycloak.services.DefaultKeycloakSessionFactory.loadFactories(DefaultKeycloakSessionFactory.java:217)       在org.keycloak.keycloak-services@6.0.1//org.keycloak.services.DefaultKeycloakSessionFactory.deploy(DefaultKeycloakSessionFactory.java:115)上       在org.keycloak.keycloak-services@6.0.1//org.keycloak.provider.ProviderManagerRegistry.deploy(ProviderManagerRegistry.java:42)       在org.keycloak.keycloak-wildfly-server-subsystem@6.0.1//org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor.deploy(KeycloakProviderDeploymentProcessor.java:55)       在org.jboss.as.server@8.0.0.Final//org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:176)       ...另外8个   由以下原因引起:java.lang.ClassNotFoundException:服务模块加载程序中的[module“ deployment.spi-1.0.0.jar”中的org.keycloak.theme.FreeMarkerUtil       在org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)       在org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)       在org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)       在org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)       ...另外14个

我也尝试了模块方法,但随后得到了NullPointerException:

  

09:23:09,394错误[org.keycloak.services.error.KeycloakErrorHandler](默认任务1)未捕获的服务器错误:java.lang.NullPointerException       在org.keycloak.keycloak-services@6.0.1//org.keycloak.protocol.AuthorizationEndpointBase.createAuthenticationSession(AuthorizationEndpointBase.java:193)上       在org.keycloak.keycloak-services@6.0.1//org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:141)       在org.keycloak.keycloak-services@6.0.1//org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:108)       在java.base / jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(本机方法)       在java.base / jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)       在java.base / jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)       在java.base / java.lang.reflect.Method.invoke(Method.java:566)       在org.jboss.resteasy.resteasy-jaxrs@3.6.3.Final//org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:139)...

我一直在关注官方文档。我的其他自定义Pbkdf2PasswordHashProvider实际上也很好。我在这里想念东西吗?

来源

import org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.theme.FreeMarkerUtil;

public class CustomFreeMarkerLoginFormsProvider extends FreeMarkerLoginFormsProvider {

    public CustomFreeMarkerLoginFormsProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
        super(session, freeMarker);
        setAttribute("isAdmin", uriInfo.getPath().contains("admin"));
    }
}

2 个答案:

答案 0 :(得分:0)

我可能会为您找到解决方案(我遇到了类似的问题,现在正在为我工​​作),告诉我是否对您也有用。 我认为您的CustomFreeMarkerLoginFormsProvider附带的代码中有一个CustomFreeMarkerLoginFormsProviderFactory。

public class CustomFreeMarkerLoginFormsFactory extends FreeMarkerLoginFormsProviderFactory {

private FreeMarkerUtil freeMarker;

@Override
public LoginFormsProvider create(KeycloakSession session) {
    return new CustomFreeMarkerLoginFormsProvider(session, freeMarker);
}

@Override
public void init(Config.Scope config) {
    freeMarker = new FreeMarkerUtil();
}

@Override
public void postInit(KeycloakSessionFactory factory) {}

@Override
public void close() {
    freeMarker = null;
}

@Override
public String getId() {
    return "customfreemarker";
}

}

然后,您需要像下面这样在standalone-configuration.cli中激活您的提供程序:

  

嵌入式服务器--server-config = standalone.xml
  / subsystem = keycloak-server / spi = login:add()
  / subsystem = keycloak-server / spi = login / provider = freemarker:add(enabled =“ false”)
  / subsystem = keycloak-server / spi = login / provider = customfreemarker:add(enabled =“ true”)

似乎您不需要激活登录提供程序的自定义工厂。我保留默认ID“ freemarker”,并将其考虑在内,而不是默认工厂。只有登录提供程序工厂像这样工作,不知道为什么。

当我像下面这样更改具有与原始类FreeMarkerLoginFormsProviderFactory相同功能的功能时,它可以工作(并且您不再需要standalone.xml中的行):

@Override
public String getId() {
    return "freemarker";
}

我认为这是Keycloak问题/改进??因为它可以与您所说的其他提供商一起很好地工作。但是我在密钥斗篷问题中什么都没找到。问题出现在v4.4.0.Final和4.5.0.Final之间。 让我知道你的进展。

答案 1 :(得分:0)

我在FreeMarkerAccountProvider / FreeMarkerAccountProviderFactory上也有类似情况,并且正在收到java.lang.NoClassDefFoundError: org/keycloak/theme/FreeMarkerUtil

这解决了问题Keycloak plugin using keycloak-services

由于我正在使用Keycloak Deployer来注册提供程序。似乎并没有解决所有依赖关系,因此我创建了一个jboss-deployment-structure.xml文件,其依赖关系位于src / main / resources / META-INF下。这里的示例jboss-deployment- structure.xml

我还必须禁用现有的提供程序,然后激活我的提供程序。为此,我在<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">标签中的standalone.xlm中添加了以下内容:

<spi name="account">
  <provider name="freemarker" enabled="false"/>
  <provider name="myfreemarker" enabled="true"/>
</spi>
相关问题