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期间挂起的多线程事务