使用WSS4J进行安全的Web服务调用返回“发现错误处理<wsse:security>标头”</wsse:security>

时间:2012-04-12 14:32:04

标签: java ws-security wss4j

我正在尝试使用WSS4J从我的客户端向Web服务调用添加密码摘要WS-Security位。我使用Axis的WSDL4J从WSDL生成客户端类,并按照说明使用WSS4J将WS-Security的“密码摘要”头添加到SOAP消息中,但返回错误消息“发现处理头的错误”。添加调试消息,看起来我的CallbackHandler不会受到影响。我做错了什么吗?或者我错过了一些WSS4J文档中无法解释的安装文件?

class CSProvider {
    public CS get(CSService csService, URL url, String username)
            throws ServiceException {
        CS csPort = csService.getCSPort(url);

        ((Stub) csPort)._setProperty(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
        ((Stub) csPort)._setProperty(WSHandlerConstants.USER, username);
        ((Stub) csPort)._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PW_DIGEST);
        ((Stub) csPort)._setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, "com.example.namespace.to.PasswordCallbackHandler");

        return csPort;   
    }
}

public class PasswordCallbackHandler implements CallbackHandler {

    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (Callback callback : callbacks) {
            if (callback instanceof WSPasswordCallback) {
                ((WSPasswordCallback) callback).setPassword(PasswordStore.getPassword());
            } else {
                throw new UnsupportedCallbackException(callback);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

经过多次探索,我发现了这个问题。正如我所料,Web服务请求在没有通过PasswordCallbackHandler的情况下发出,因此它们返回时带有来自远程服务器的给定错误消息,该消息期望有效的身份验证凭据。花了我一段时间才确定的是我需要构建服务定位器(在这种情况下为csService),如下所示:

CSService csService = new CSServiceLocator(new FileProvider("client_deploy.wsdd"));

使用client_deploy.wsdd文件,如下所示:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
    <globalConfiguration>
        <requestFlow>
            <handler name="csHandler" type="java:org.apache.ws.axis.security.WSDoAllSender"/>
        </requestFlow>
    </globalConfiguration>
</deployment>

然后从CSProvider.get()设置属性就可以了。

我避免使用wsdd文件,因为我看到的所有其他示例都使用它来设置用户名和密码类 - 这是我在运行时才知道的两件事。明智的一句话:当文档说你可以使用_setProperty()方法而不是一个wsdd文件时,它只意味着设置这些属性,而不是完全替换文件。