7.3. 提供客户端凭证

概述

提供 UsernameToken 客户端凭证基本上有两种方法:您可以在客户端的 Blueprint XML 配置中直接设置用户名和密码;或者,您可以在客户端配置中设置用户名并实施回调处理程序以以编程方式提供密码。后一种方法(通过编程)可以方便密码在视图中显示。

客户端凭证属性

表 7.1 “客户端凭证属性” 显示在 Blueprint XML 中客户端请求上下文上指定 WS-Security username/password 凭据的属性。

表 7.1. 客户端凭证属性

Properties描述

security.username

指定 UsernameToken policy assertions 的用户名。

security.password

指定 UsernameToken policy assertions 的密码。如果未指定,则可通过调用回调处理程序来获取密码。

security.callback-handler

指定 WSS4J 回调处理器的类名称,用于检索 UsernameToken 策略断言的密码。请注意,回调处理器也可以处理其他类型的安全事件。

在 Blueprint XML 中配置客户端凭证

要在 Blueprint XML 中客户端请求上下文中配置用户名/密码凭证,请按如下所示设置 security.usernamesecurity.password 属性:

<beans ... >
    <jaxws:client name="{NamespaceName}LocalPortName"
                  createdFromAPI="true">
        <jaxws:properties>
            <entry key="security.username" value="Alice"/>
            <entry key="security.password" value="abcd!1234"/>
        </jaxws:properties>
    </jaxws:client>
    ...
</beans>

如果您不希望直接在 Blueprint XML 中存储密码(这可能是安全风险),您可以使用回调处理程序提供密码。

为密码编程回调处理器

如果要使用回调处理器为 UsernameToken 标头提供密码,您必须首先修改 Blueprint XML 中的客户端配置,将 security.callback-handler 设置替换为 security.callback-handler 设置,如下所示:

<beans ... >
    <jaxws:client name="{NamespaceName}LocalPortName"
                  createdFromAPI="true">
        <jaxws:properties>
            <entry key="security.username" value="Alice"/>
            <entry key="security.callback-handler" value="interop.client.UTPasswordCallback"/>
        </jaxws:properties>
    </jaxws:client>
    ...
</beans>

在前面的示例中,回调处理程序由 UT PasswordCallback 类实施。您可以通过实施 javax.security.auth.callback.CallbackHandler 接口来编写回调处理程序,如 例 7.2 “UsernameToken 密码的回调处理程序” 所示。

例 7.2. UsernameToken 密码的回调处理程序

package interop.client;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class UTPasswordCallback implements CallbackHandler {

    private Map<String, String> passwords =
        new HashMap<String, String>();

    public UTPasswordCallback() {
        passwords.put("Alice", "ecilA");
        passwords.put("Frank", "invalid-password");
        //for MS clients
        passwords.put("abcd", "dcba");
    }

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
            WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];

            String pass = passwords.get(pc.getIdentifier());
            if (pass != null) {
                pc.setPassword(pass);
                return;
            }
        }

        throw new IOException();
    }

    // Add an alias/password pair to the callback mechanism.
    public void setAliasPassword(String alias, String password) {
        passwords.put(alias, password);
    }
}

回调功能通过 CallbackHandler.handle() 方法实施。在本例中,假设传递给 handle() 方法的回调对象是 org.apache.ws.security.WSPasswordCallback 类型(在更现实示例中,您将检查回调对象的类型)。

客户端回调处理器的更真实的实施可能由提示用户输入其密码组成。

WSPasswordCallback 类

在 Apache CXF 客户端中调用一个 回调处理程序 时,用于设置 UsernameToken 密码的目的,对应的 WSPasswordCallback 对象具有 USERNAME_TOKEN 使用代码。

有关 WSPasswordCallback 类的更多详情,请参阅 org.apache.ws.security.WSPasswordCallback

WSPasswordCallback 类定义了几种不同的使用代码,如下所示:

USERNAME_TOKEN

获取 UsernameToken 凭证的密码。该使用代码在客户端(用于获取发送到服务器的密码之间)和服务器端(获取密码)与客户端接收的密码进行比较。

在服务器端,在以下情况下设置这个代码:

  • 摘要密码- 如果 UsernameToken 包含摘要密码,则回调必须为给定用户名返回对应的密码(given by WSPasswordCallback.getIdentifier())。验证密码(与摘要密码进行比较)由 WSS4J 运行时完成。
  • 纯文本密码- 实施与摘要密码相同的方法(自 Apache CXF 2.4.0 开始)。
  • 自定义密码类型- 如果 getHandleCustomPasswordTypes()org.apache.ws.security.WSSConfig 上为 true,则此例的实施方式与摘要密码问题单相同(自 Apache CXF 2.4.0 开始。否则,会抛出异常。

    如果服务器端的已接收 UsernameToken 中没有包括 Password 元素,则回调处理程序不会被调用(自 Apache CXF 2.4.0 起)。

DECRYPT
需要密码从 Java 密钥存储检索私钥,其中 WSPasswordCallback.getIdentifier() 提供密钥存储条目的别名。WSS4J 使用这个私钥解密会话(symmetric)密钥。
签名
需要密码从 Java 密钥存储检索私钥,其中 WSPasswordCallback.getIdentifier() 提供密钥存储条目的别名。WSS4J 使用此私钥生成签名。
SECRET_KEY
需要密钥进行加密或签名,或者在入站端进行解密或验证。回调处理程序必须使用 setKey(byte[]) 方法设置密钥。
SECURITY_CONTEXT_TOKEN
需要 wsc:SecurityContextToken 的密钥,通过调用 setKey(byte[]) 方法提供它。
CUSTOM_TOKEN
需要令牌作为 DOM 元素。例如,这用于对不在消息中的 SAML Assertion 或 SecurityContextToken 的引用。回调处理程序必须使用 setCustomToken(Element) 方法设置令牌。
KEY_NAME
(过时的) Since Apache CXF 2.4.0,这个使用代码已过时。
USERNAME_TOKEN_UNKNOWN
(过时的) Since Apache CXF 2.4.0,这个使用代码已过时。
UNKNOWN
WSS4J 未使用。