JBoss EAP 7.4+Elytron同主机远程EJB的JBOSS-LOCAL-USER认证异常
问题背景与现象
我们在域模式下运行JBoss EAP 7.4.11(基于OpenJDK 11.0.20),通过docs/examples/enable-elytron-se17-domain.cli脚本配置Elytron子系统。应用间通过远程EJB调用,已在Elytron中配置authentication-configuration和authentication-context,并在Remoting子系统的remote-outbound-connection中引用该认证上下文,配置与官方文档一致。
但同主机内的本地EJB调用时,JBoss会使用JBOSS-LOCAL-USER认证机制,导致认证失败,错误信息如下:
JBREM000308: Authentication failed (no mechanisms left), tried: JBOSS-LOCAL-USER: org.wildfly.security.auth.AuthenticationException: JBREM000304: Server rejected authentication
启用被调用实例的跟踪日志后,发现系统尝试用不存在的$local用户认证,且问题随机出现。临时添加$local用户可绕过,但这并非合理方案,需确认是否为JBoss自身问题并获取正确解决方法。
跟踪日志片段
2023-08-01 19:59:24,020 TRACE [org.jboss.remoting.remote] (default I/O-2) Received authentication request, id b4e72a33, mech JBOSS-LOCAL-USER 2023-08-01 19:59:24,020 TRACE [org.jboss.remoting.remote] (default I/O-2) Received authentication request for ID b4e72a33, mech JBOSS-LOCAL-USER ... 2023-08-01 19:59:24,020 TRACE [org.wildfly.security] (default task-4) Handling SocketAddressCallback 2023-08-01 19:59:24,020 TRACE [org.wildfly.security] (default task-4) Handling SocketAddressCallback 2023-08-01 19:59:24,020 TRACE [org.wildfly.security] (default task-4) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='server.domain.loc' protocol='remote' 2023-08-01 19:59:24,020 TRACE [org.wildfly.security] (default task-4) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='server.domain.loc' protocol='remote' 2023-08-01 19:59:24,020 TRACE [org.wildfly.security] (default task-4) Creating SaslServer [org.wildfly.security.sasl.localuser.LocalUserServer@58583e7f] for mechanism [JBOSS-LOCAL-USER] and protocol [remote] 2023-08-01 19:59:24,020 TRACE [org.wildfly.security] (default task-4) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@66bb693a->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@14bb462f->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@c74c779->org.wildfly.security.sasl.localuser.LocalUserServer@58583e7f] for mechanism [JBOSS-LOCAL-USER] 2023-08-01 19:59:24,021 TRACE [org.jboss.remoting.remote] (default task-4) Sending authentication challenge for ID b4e72a33 ... 2023-08-01 19:59:24,021 TRACE [org.wildfly.security] (default task-4) Handling NameCallback: authenticationName = $local 2023-08-01 19:59:24,021 TRACE [org.wildfly.security] (default task-4) Principal assigning: [$local], pre-realm rewritten: [$local], realm name: [local], post-realm rewritten: [$local], realm rewritten: [$local] 2023-08-01 19:59:24,021 TRACE [org.wildfly.security] (default task-4) PropertiesRealm: identity [$local] does not exist 2023-08-01 19:59:24,021 TRACE [org.wildfly.security] (default task-4) Authorization failed - realm identity does not exists 2023-08-01 19:59:24,021 TRACE [org.wildfly.security] (default task-4) Handling AuthorizeCallback: authenticationID = $local authorizationID = $local authorized = false 2023-08-01 19:59:24,021 TRACE [org.jboss.remoting.remote] (default task-4) Authentication failed at response evaluation: javax.security.sasl.SaslException: ELY05014: Authentication mechanism authorization failed: "$local" running as "$local" at org.wildfly.security.elytron-private@1.15.16.Final-redhat-00001//org.wildfly.security.sasl.localuser.LocalUserServer.evaluateMessage(LocalUserServer.java:262) at org.wildfly.security.elytron-private@1.15.16.Final-redhat-00001//org.wildfly.security.sasl.util.AbstractSaslParticipant.evaluateMessage(AbstractSaslParticipant.java:219) at org.wildfly.security.elytron-private@1.15.16.Final-redhat-00001//org.wildfly.security.sasl.util.AbstractSaslServer.evaluateResponse(AbstractSaslServer.java:82) at org.wildfly.security.elytron-private@1.15.16.Final-redhat-00001//org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1.evaluateResponse(AuthenticationCompleteCallbackSaslServerFactory.java:58) at org.wildfly.security.elytron-private@1.15.16.Final-redhat-00001//org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer.evaluateResponse(AuthenticationTimeoutSaslServerFactory.java:110) at org.wildfly.security.elytron-private@1.15.16.Final-redhat-00001//org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1.evaluateResponse(SecurityIdentitySaslServerFactory.java:59) at org.jboss.remoting@5.0.27.Final-redhat-00001//org.jboss.remoting3.ConnectionImpl.lambda$receiveAuthResponse$3(ConnectionImpl.java:274) at org.jboss.remoting@5.0.27.Final-redhat-00001//org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:993) at org.jboss.threads@2.4.0.Final-redhat-00001//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) at org.jboss.threads@2.4.0.Final-redhat-00001//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990) at org.jboss.threads@2.4.0.Final-redhat-00001//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486) at org.jboss.threads@2.4.0.Final-redhat-00001//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377) at org.jboss.xnio@3.8.9.Final-redhat-00001//org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282) at java.base/java.lang.Thread.run(Thread.java:829)
相关配置片段
Elytron子系统配置
<subsystem xmlns="urn:wildfly:elytron:13.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto"> <authentication-client> <authentication-configuration name="MH-ejb-auth-config" authentication-name="mhejb"> <credential-reference clear-text="password"/> </authentication-configuration> <authentication-configuration name="TF-ejb-auth-config" authentication-name="tfejb"> <credential-reference clear-text="password"/> </authentication-configuration> <authentication-context name="MH-ejb-auth-context"> <match-rule match-port="8080" authentication-configuration="MH-ejb-auth-config"/> </authentication-context> <authentication-context name="TF-ejb-auth-context"> <match-rule match-port="8100" authentication-configuration="TF-ejb-auth-config"/> </authentication-context> </authentication-client> ... </subsystem>
Remoting子系统配置
<subsystem xmlns="urn:jboss:domain:remoting:4.0"> <http-connector name="http-remoting-connector" connector-ref="default" sasl-authentication-factory="application-sasl-authentication"/> <outbound-connections> <remote-outbound-connection name="MH-remote-ejb-connection-1" outbound-socket-binding-ref="MH-remote-ejb-1" authentication-context="MH-ejb-auth-context"> <properties> <property name="SASL_POLICY_NOANONYMOUS" value="false"/> <property name="SSL_ENABLED" value="false"/> <property name="READ_TIMEOUT" value="120000"/> </properties> </remote-outbound-connection> <remote-outbound-connection name="TF-remote-ejb-connection-1" outbound-socket-binding-ref="TF-remote-ejb-1" authentication-context="TF-ejb-auth-context"> <properties> <property name="SASL_POLICY_NOANONYMOUS" value="false"/> <property name="SSL_ENABLED" value="false"/> <property name="READ_TIMEOUT" value="120000"/> </properties> </remote-outbound-connection> </outbound-connections> </subsystem>
Socket绑定配置
<socket-binding-group name="GS-ha-sockets" default-interface="public"> <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/> <socket-binding name="http" port="${jboss.http.port:8080}"/> <socket-binding name="https" port="${jboss.https.port:8443}"/> <socket-binding name="jgroups-mping" interface="private" multicast-address="${jboss.default.multicast.address:231.0.40.4}" multicast-port="45740"/> <socket-binding name="jgroups-tcp" interface="private" port="7600"/> <socket-binding name="jgroups-tcp-fd" interface="private" port="57600"/> <socket-binding name="jgroups-udp" interface="private" port="55200" multicast-address="${jboss.default.multicast.address:231.0.40.4}" multicast-port="45728"/> <socket-binding name="jgroups-udp-fd" interface="private" port="54200"/> <socket-binding name="modcluster" multicast-address="${jboss.modcluster.multicast.address:225.0.41.105}" multicast-port="23404"/> <socket-binding name="txn-recovery-environment" port="4712"/> <socket-binding name="txn-status-manager" port="4713"/> <outbound-socket-binding name="MH-remote-ejb-1"> <remote-destination host="server.domain.loc" port="8080"/> </outbound-socket-binding> <outbound-socket-binding name="TF-remote-ejb-1"> <remote-destination host="server.domain.loc" port="8100"/> </outbound-socket-binding> </socket-binding-group>
解决方法
方法1:在认证配置中明确禁用JBOSS-LOCAL-USER机制
在Elytron的authentication-configuration中添加sasl-mechanism-selector,指定只使用需要的认证机制(比如DIGEST-MD5或PLAIN),排除JBOSS-LOCAL-USER:
<authentication-configuration name="MH-ejb-auth-config" authentication-name="mhejb"> <credential-reference clear-text="password"/> <sasl-mechanism-selector selector="DIGEST-MD5,PLAIN !JBOSS-LOCAL-USER"/> </authentication-configuration>
这样强制客户端使用指定的认证机制,不会 fallback 到JBOSS-LOCAL-USER。
方法2:调整远程出站连接的SASL策略
在Remoting的remote-outbound-connection属性中,添加SASL_MECHANISMS属性,指定允许的认证机制:
<remote-outbound-connection name="MH-remote-ejb-connection-1" outbound-socket-binding-ref="MH-remote-ejb-1" authentication-context="MH-ejb-auth-context"> <properties> <property name="SASL_POLICY_NOANONYMOUS" value="false"/> <property name="SSL_ENABLED" value="false"/> <property name="READ_TIMEOUT" value="120000"/> <property name="SASL_MECHANISMS" value="DIGEST-MD5,PLAIN"/> </properties> </remote-outbound-connection>
这会限制客户端只能使用指定的SASL机制,避免触发JBOSS-LOCAL-USER。
方法3:修复本地用户映射逻辑(不推荐)
如果需要保留本地用户认证能力,可在Elytron的安全域中配置允许$local用户,或调整LOCAL-USER机制的授权规则。但此方式会引入不必要的安全风险,仅作为特殊场景下的备选方案。
方法4:检查主机名解析与绑定配置
问题随机出现可能和主机名解析有关,确保同主机调用时,客户端和服务器使用的地址一致。可尝试将出站socket绑定的host改为127.0.0.1而非域名,避免DNS解析导致的本地/远程判断异常。
内容的提问来源于stack exchange,提问作者Petr H

