5

我正在尝试为 Web 服务编写一个拦截器,该拦截器将在发送到端点之前修改 Soap 消息的内容。如果客户端发送了某个元素的值为 1 的消息,我希望能够将该元素更改为 2,以便当消息到达端点时,客户端看起来好像提交了 2 而不是1. 我不确定这是一个让我难以捉摸的困难任务,还是一个我正在做的比它需要的更难的简单任务。

我已经通过了一些 Spring 拦截器;但是验证和日志拦截器并不是每个都会改变正在传输的消息。Wss4jSecurityInterceptor 确实向 MessageContext 添加了一些属性;但我无法利用它正在做的任何事情。我有一个拦截器的外壳;但没有做任何有价值的事情。

public boolean handleRequest(MessageContext messageContext, Object endpoint)
        throws Exception {

    SaajSoapMessage saajSoapMessage = (SaajSoapMessage) messageContext
            .getRequest();
    SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
    SOAPBody soapBody = soapMessage.getSOAPBody();

    return true;
}

我希望有机会其他人已经解决了这个特殊问题。任何见解将不胜感激。谢谢。

4

3 回答 3

6

修改有效载荷有点棘手。我发现完成这项工作的唯一方法是使用getPayloadSource()getPayloadResult()方法SoapBody,它公开javax.xml.transform了用于操作数据的友好对象。

这是令人讨厌的重量级,但你可以做这样的事情:

Transformer identityTransform = TransformerFactory.newInstance().newTransformer();
DOMResult domResult = new DOMResult();
identityTransform.transform(soapBody.getPayloadSource(), domResult);

Node bodyContent = domResult.getNode(); // modify this

identityTransform.transform(new DOMSource(bodyContent), soapBody.getPayloadResult());

我很想看到一个更好的方法来做到这一点。

于 2010-07-22T21:15:38.243 回答
1

我意识到稍后更改请求会更容易。我不需要修改原始 SOAP 消息,只要我能够在数据到达我的端点之前对其进行修改。

我正在使用的端点都扩展了 AbstractDom4jPayloadEndpoint - 所以我将这些端点包装在一个代理中,允许我在继续我的端点之前修改请求元素。IE:

public class MyProxyEndpoint extends AbstractDom4jPayloadEndpoint

    @Override
    protected Element invokeInternal( 
        Element requestElement,
        Document responseDocument ) throws Exception
    {
        if( requestElement != null )
        {
            // alter request element
        }

        return ( Element ) this.invokeMethod.invoke( 
            this.target,
            requestElement,
            responseDocument );
    }
于 2010-07-28T18:03:29.913 回答
1

我修改了这个答案中的代码,将一个<authentication/>元素插入到所有 SOAP 正文请求中:

@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
    logger.trace("Enter handleMessage");
    try {
        SaajSoapMessage request = (SaajSoapMessage) messageContext.getRequest();
        addAuthn(request);
    } catch (Exception e) {
        logger.error(e.getMessage(),e);
    }

    return true;
}

protected void addAuthn(SaajSoapMessage request) throws TransformerException {
    Transformer identityTransform = TransformerFactory.newInstance().newTransformer();
    DOMResult domResult = new DOMResult();
    identityTransform.transform(request.getPayloadSource(), domResult);

    Node bodyContent = domResult.getNode();
    Document doc = (Document) bodyContent;
    doc.getFirstChild().appendChild(authNode(doc));

    identityTransform.transform(new DOMSource(bodyContent), request.getPayloadResult());
}

protected Node authNode(Document doc) {
    Element authentication = doc.createElementNS(ns, "authentication");
    Element username = doc.createElementNS(ns, "username");
    username.setTextContent(authn.getUsername());
    Element password = doc.createElementNS(ns, "password");
    password.setTextContent(authn.getPassword());
    authentication.appendChild(username);
    authentication.appendChild(password);
    return authentication;
}

使用此解决方案是因为 WebServiceMessageCallback 需要我更改文档,并且 SaajSoapMessageFactory 在配置的 Jaxb2Marshaller 插入肥皂主体之前被激活。

于 2016-11-13T14:15:34.517 回答