Wildfly 24 中带有 Elytron 的多个 sasl 身份验证机制

Posted

技术标签:

【中文标题】Wildfly 24 中带有 Elytron 的多个 sasl 身份验证机制【英文标题】:Multiple sasl authentication mechanisms in Wildfly 24 with Elytron 【发布时间】:2021-11-19 14:00:31 【问题描述】:

我已将 Wildfly 设置为使用 OAUTHBEARER 身份验证机制在我的服务器和桌面应用程序之间进行远程 JNDI EJB 查找,效果很好。

但是,我还想设置一个简单的基于 .properties 文件的身份验证方法,以便在没有令牌的情况下与服务器通信以便能够请求一个,或者访问有关 keycloak 身份验证服务器的信息,因为我不想对其进行硬编码进入我的客户端应用程序,我似乎无法让它工作。无论我做什么,服务器都会拒绝我的身份验证尝试。

我试图访问 pre auth bean 的示例代码如下所示:

private static PreAuth lookUpPreAuthBean() throws NamingException 

    final Properties jndiProperties = new Properties();
            
    jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
    jndiProperties.put(Context.PROVIDER_URL,"http-remoting://localhost:8080");
            
    jndiProperties.put(Context.SECURITY_PRINCIPAL, "test");
    jndiProperties.put(Context.SECURITY_CREDENTIALS, "test");
    
    final Context initialContext = new InitialContext(jndiProperties);

    return (PreAuth) initialContext.lookup("ejb:server/server-ejb/PreAuthImpl!co.my.package.server.PreAuth");

这是我得到的堆栈跟踪:

    Suppressed: javax.security.sasl.SaslException: ELY05019: No token was given
            at org.wildfly.security.mechanism.oauth2.OAuth2Client.getInitialResponse(OAuth2Client.java:66)
            at org.wildfly.security.sasl.oauth2.OAuth2SaslClient.evaluateMessage(OAuth2SaslClient.java:62)
            at org.wildfly.security.sasl.util.AbstractSaslParticipant.evaluateMessage(AbstractSaslParticipant.java:225)
            at org.wildfly.security.sasl.util.AbstractSaslClient.evaluateChallenge(AbstractSaslClient.java:98)
            at org.wildfly.security.sasl.util.AbstractDelegatingSaslClient.evaluateChallenge(AbstractDelegatingSaslClient.java:54)
            at org.wildfly.security.sasl.util.PrivilegedSaslClient.lambda$evaluateChallenge$0(PrivilegedSaslClient.java:55)
            at java.base/java.security.AccessController.doPrivileged(Native Method)
            at org.wildfly.security.sasl.util.PrivilegedSaslClient.evaluateChallenge(PrivilegedSaslClient.java:55)
            at org.jboss.remoting3.remote.ClientConnectionOpenListener$Capabilities.lambda$handleEvent$1(ClientConnectionOpenListener.java:459)
            at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:991)
            at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
            at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
            at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
            at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1348)
            at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
            at java.base/java.lang.Thread.run(Thread.java:829)
        Suppressed: javax.security.sasl.SaslException: DIGEST-MD5: Server rejected authentication
            at org.jboss.remoting3.remote.ClientConnectionOpenListener$Authentication.handleEvent(ClientConnectionOpenListener.java:760)
            at org.jboss.remoting3.remote.ClientConnectionOpenListener$Authentication.handleEvent(ClientConnectionOpenListener.java:602)
            at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
            at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
            at org.xnio.nio.NiosocketConduit.handleReady(NioSocketConduit.java:89)
            at org.xnio.nio.WorkerThread.run(WorkerThread.java:591)

如果我要提供一个令牌,那么承载机制就可以工作,似乎由于某种原因其他机制没有进行身份验证

以下是我修改的 Wildfly 24 Standalone.xml 中的部分:

EJB 子系统:

...
<default-security-domain value="other"/>
<application-security-domains>
    <application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
...

Elytron 子系统:

我想使用 PreAuthRealm 进行简单的身份验证。
<security-domains>
    <security-domain name="ApplicationDomain" default-realm="JWTRealm" permission-mapper="default-permission-mapper">
        <realm name="JWTRealm" role-decoder="jwt-to-roles"/>
        <realm name="PreAuthRealm" role-decoder="groups-to-roles"/>
    </security-domain>
...
<\security-domains>
我想使用 application-users.properties 文件来存储用户名和密码,这些凭据是通过 add-user.sh 脚本添加到存储中的
<security-realms>
    <identity-realm name="local" identity="$local"/>
    <properties-realm name="PreAuthRealm">
        <users-properties path="application-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="PreAuthRealm"/>
        <groups-properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
    </properties-realm>
    <token-realm name="JWTRealm" principal-claim="*my claim*">
        <jwt issuer="*my issuer*" audience="account">
           <key kid="*my key id*" public-key="*my public key*"/>
        </jwt>
    </token-realm>
</security-realms>
sasl 身份验证工厂设置:
 <sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
    <mechanism-configuration>
        <mechanism mechanism-name="OAUTHBEARER">
            <mechanism-realm realm-name="JWTRealm"/>
        </mechanism>
        <mechanism mechanism-name="DIGEST-MD5">
            <mechanism-realm realm-name="PreAuthRealm"/>
        </mechanism>   
    </mechanism-configuration>
</sasl-authentication-factory>

远程子系统:

<subsystem xmlns="urn:jboss:domain:remoting:4.0">
    <http-connector name="http-remoting-connector" connector-ref="default" sasl-authentication-factory="application-sasl-authentication"/>
</subsystem>

奇怪的是,如果我从远程处理子系统中删除sasl-authentication-factory="application-sasl-authentication",并放回原来的security-realm="ApplicationRealm",上面的代码就会运行,它实际上是从 .properties 文件中对我进行身份验证,但是当然是不记名令牌部分不起作用,这是重点。

我在这里的设置缺少什么?我想实现的目标有可能吗?

【问题讨论】:

【参考方案1】:

不是解决方案,而是解决方法。通过不将领域命名为 "PreAuthRealm" 而是将其命名为默认的 "ApplicationRealm" 来设法使其工作,并且无论出于何种原因将此领域设置为安全域中的默认领域,这和 JWT 领域都可以工作。将 "JWTRealm" 设置为默认值只会使 JWT 领域工作。

【讨论】:

以上是关于Wildfly 24 中带有 Elytron 的多个 sasl 身份验证机制的主要内容,如果未能解决你的问题,请参考以下文章

Wildfly 11 Elytron - 基于属性文件的身份验证失败,未安装所需的服务

如何将 PicketBox 自定义登录模块迁移到 Elytron?

为基于Wildfly容器的身份验证生成salted /哈希密码

通过wildfly将实体持久化到postgresql期间挂起的多线程事务

AFNetworking 3.0 中带有图像和其他参数的多部分数据

在 asp.net 中带有复选框的多选下拉列表