2.2. 使用 Elytron 传播和转发身份


2.2.1. 为远程调用传播安全标识符

JBoss EAP 7.1 引入了轻松配置服务器和应用,从而将安全身份从客户端传播到服务器以进行远程调用。您还可以将服务器组件配置为在给定用户的安全身份中运行。

本节中的示例演示了如何转发安全身份凭据。它将客户端和 EJB 的安全身份传播到远程 EJB。它返回一个字符串,其中包含名为远程 EJB 的 Principal 的名称,以及用户的授权角色信息。该示例由以下组件组成:

  • 个安全的 EJB,它包含一个可由所有用户访问的方法,它将返回有关调用者的授权信息。
  • 包含单一方法的中间 EJB。它利用远程连接,并在受保护的 EJB 上调用方法。
  • 调用中间 EJB 的远程独立客户端应用。
  • META-INF/wildfly-config.xml 文件,其中包含用于身份验证的身份信息。

您必须首先通过配置服务器来启用安全身份传播。接下来 查看使用 WildFlyInitialContextFactory 查找和调用远程 EJB 的示例应用代码

配置服务器以进行安全传播
  1. 配置 ejb3 子系统,以使用 Elytron ApplicationDomain

    /subsystem=ejb3/application-security-domain=quickstart-domain:add(security-domain=ApplicationDomain)
    Copy to Clipboard Toggle word wrap

    这会将以下 application-security-domain 配置添加到 ejb3 子系统:

    <subsystem xmlns="urn:jboss:domain:ejb3:5.0">
        ....
        <application-security-domains>
            <application-security-domain name="quickstart-domain" security-domain="ApplicationDomain"/>
        </application-security-domains>
    </subsystem>
    Copy to Clipboard Toggle word wrap
  2. 添加 PLAIN 身份验证配置,以发送纯文本用户名和密码,以及用于出站连接的身份验证上下文。有关支持身份传播的机制列表,请参阅支持安全身份传播的机制

    /subsystem=elytron/authentication-configuration=ejb-outbound-configuration:add(security-domain=ApplicationDomain,sasl-mechanism-selector="PLAIN")
    /subsystem=elytron/authentication-context=ejb-outbound-context:add(match-rules=[{authentication-configuration=ejb-outbound-configuration}])
    Copy to Clipboard Toggle word wrap

    这会将下列 authentication-client 配置添加到 elytron 子系统:

    <subsystem xmlns="urn:wildfly:elytron:4.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
        <authentication-client>
            <authentication-configuration name="ejb-outbound-configuration" security-domain="ApplicationDomain" sasl-mechanism-selector="PLAIN"/>
            <authentication-context name="ejb-outbound-context">
                <match-rule authentication-configuration="ejb-outbound-configuration"/>
            </authentication-context>
        </authentication-client>
        ....
    </subsystem>
    Copy to Clipboard Toggle word wrap
  3. 将远程目的地出站套接字绑定到 standard-sockets 套接字绑定。

    /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=ejb-outbound:add(host=localhost,port=8080)
    Copy to Clipboard Toggle word wrap

    这会将以下 ejb-outbound 出站套接字绑定添加到 standard-sockets 套接字绑定组中。

    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
        ....
        <outbound-socket-binding name="ejb-outbound">
            <remote-destination host="localhost" port="8080"/>
        </outbound-socket-binding>
    </socket-binding-group>
    Copy to Clipboard Toggle word wrap
  4. 添加远程出站连接,并在 HTTP 连接器中设置 SASL 身份验证工厂。

    /subsystem=remoting/remote-outbound-connection=ejb-outbound-connection:add(outbound-socket-binding-ref=ejb-outbound, authentication-context=ejb-outbound-context)
    /subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=sasl-authentication-factory,value=application-sasl-authentication)
    Copy to Clipboard Toggle word wrap

    这会将以下 http-remoting-connectorejb-outbound-connection 配置添加到 远程子系统:

    <subsystem xmlns="urn:jboss:domain:remoting:4.0">
        ....
        <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm" sasl-authentication-factory="application-sasl-authentication"/>
        <outbound-connections>
            <remote-outbound-connection name="ejb-outbound-connection" outbound-socket-binding-ref="ejb-outbound" authentication-context="ejb-outbound-context"/>
        </outbound-connections>
    </subsystem>
    Copy to Clipboard Toggle word wrap
  5. 将 Elytron SASL 身份验证配置为使用 PLAIN 机制。

    /subsystem=elytron/sasl-authentication-factory=application-sasl-authentication:write-attribute(name=mechanism-configurations,value=[{mechanism-name=PLAIN},{mechanism-name=JBOSS-LOCAL-USER,realm-mapper=local},{mechanism-name=DIGEST-MD5,mechanism-realm-configurations=[{realm-name=ApplicationRealm}]}])
    Copy to Clipboard Toggle word wrap

    这会将以下 application-sasl-authentication 配置添加到 elytron 子系统:

    <subsystem xmlns="urn:wildfly:elytron:4.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
        ....
        <sasl>
          ....
          <sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
              <mechanism-configuration>
                  <mechanism mechanism-name="PLAIN"/>
                  <mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/>
                  <mechanism mechanism-name="DIGEST-MD5">
                      <mechanism-realm realm-name="ApplicationRealm"/>
                  </mechanism>
              </mechanism-configuration>
          </sasl-authentication-factory>
      </sasl>
      ....
    </subsystem>
    Copy to Clipboard Toggle word wrap

服务器现在已配置为为以下示例应用启用安全传播:

查看传播安全身份的应用程序代码示例

在服务器配置中启用了安全身份传播后,EJB 客户端应用可以使用 WildFlyInitialContextFactory 来查找并调用 EJB 代理。EJB 将作为在客户端示例中验证的用户身份调用,如下所示:以下缩写的代码示例取自 JBoss EAP 7.3 附带的 ejb-security-context-propagation 快速入门:有关安全身份传播的完整工作示例,请参见 Quickstart。

若要以其他用户身份调用 EJB,您可以在上下文属性中设置 Context.SECURITY_PRINCIPALContext.SECURITY_CREDENTIALS

示例:远程客户端

public class RemoteClient {

    public static void main(String[] args) throws Exception {
        // invoke the intermediate bean using the identity configured in wildfly-config.xml
        invokeIntermediateBean();

        // now lets programmatically setup an authentication context to switch users before invoking the intermediate bean
        AuthenticationConfiguration superUser = AuthenticationConfiguration.empty().setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("PLAIN")).
                useName("superUser").usePassword("superPwd1!");
        final AuthenticationContext authCtx = AuthenticationContext.empty().
                with(MatchRule.ALL, superUser);

        AuthenticationContext.getContextManager().setThreadDefault(authCtx);
        invokeIntermediateBean();
    }

    private static void invokeIntermediateBean() throws Exception {
        final Hashtable<String, String> jndiProperties = new Hashtable<>();
        jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
        jndiProperties.put(Context.PROVIDER_URL, "remote+http://localhost:8080");
        final Context context = new InitialContext(jndiProperties);
        IntermediateEJBRemote intermediate = (IntermediateEJBRemote) context.lookup("ejb:/ejb-security-context-propagation/IntermediateEJB!"
                + IntermediateEJBRemote.class.getName());
        // Call the intermediate EJB
        System.out.println(intermediate.makeRemoteCalls());
    }
}
Copy to Clipboard Toggle word wrap

示例:中间 EJB

@Stateless
@Remote(IntermediateEJBRemote.class)
@SecurityDomain("quickstart-domain")
@PermitAll
public class IntermediateEJB implements IntermediateEJBRemote {

    @EJB(lookup="ejb:/ejb-security-context-propagation/SecuredEJB!org.jboss.as.quickstarts.ejb_security_context_propagation.SecuredEJBRemote")
    private SecuredEJBRemote remote;

    @Resource
    private EJBContext context;

    public String makeRemoteCalls() {
        try {
            StringBuilder sb = new StringBuilder("** ").
                    append(context.getCallerPrincipal()).
                    append(" * * \n\n");
            sb.append("Remote Security Information: ").
                    append(remote.getSecurityInformation()).
                    append("\n");

            return sb.toString();
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            throw new RuntimeException("Teasting failed.", e);
        }
    }
}
Copy to Clipboard Toggle word wrap

示例:Secured EJB

@Stateless
@Remote(SecuredEJBRemote.class)
@SecurityDomain("quickstart-domain")
public class SecuredEJB implements SecuredEJBRemote {

    @Resource
    private SessionContext context;

    @PermitAll
    public String getSecurityInformation() {
        StringBuilder sb = new StringBuilder("[");
        sb.append("Principal=[").
                append(context.getCallerPrincipal().getName()).
                append("], ");
        userInRole("guest", sb).append(", ");
        userInRole("user", sb).append(", ");
        userInRole("admin", sb).append("]");
        return sb.toString();
    }
}
Copy to Clipboard Toggle word wrap

示例:wildfly-config.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <authentication-client xmlns="urn:elytron:client:1.2">
        <authentication-rules>
            <rule use-configuration="default"/>
        </authentication-rules>
        <authentication-configurations>
            <configuration name="default">
                <set-user-name name="quickstartUser"/>
                <credentials>
                    <clear-password password="quickstartPwd1!"/>
                </credentials>
                <sasl-mechanism-selector selector="PLAIN"/>
                <providers>
                    <use-service-loader />
                </providers>
            </configuration>
        </authentication-configurations>
    </authentication-client>
</configuration>
Copy to Clipboard Toggle word wrap

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat