如何使用 SOAPHandlers 对 MTOM SOAP 消息进行签名



目前,我有两个处理程序,一个用于日志记录,一个用于对 SOAP 消息进行签名(它本质上会篡改 SOAP 消息)。如果没有处理程序链,MTOM 将按预期工作,插入对二进制内容的引用,而不是内联 base64 二进制内容。

一旦我引入了处理程序,MTOM 内容现在就以内联方式包含在内联中。

是否可以使用处理程序对 SOAP 消息进行签名,或者是否有更合适的方法来执行此操作?

更新 1无法发布完整源代码。本质上,自定义SOAPHandler实现。它对时间戳(在标头中)、自定义标头和 SOAP 正文执行一些基本的 XMLDsig 类型操作。然后将生成的摘要值注入到标头中的签名元素中。

关于记录器,它又是一个简单的SOAPHandler。如果以独占方式使用它或签名处理程序,则结果是相同的,即内联字节内容的 MTOM 消息。我取得的唯一进展是使用消息处理程序进行日志记录。这允许我输出 SOAP 信封(尽管字节内容是内联的),并且仍然保持 MTOM 分隔。因此,这不是真正的解决方案,而是指示 SOAP 消息的任何修改都需要在较低级别进行。这引导我走上了管子的道路。

更新 2

以下是MessageHandler方法的示例。您可以看到原始 HTTP 转储将包含多部分消息,而实际输出内联 base64。此影响与SOAPHandler实现之间的唯一区别是,实际的 HTTP 请求更改为单个部分内联 MTOM 消息。

@Override
public boolean handleMessage(MessageHandlerContext context) {
  HttpTransportPipe.dump = true;
  Boolean isOutgoing = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  if (isOutgoing) {
    System.out.println("nOutbound message:");
    XMLStreamWriter writer = XMLStreamWriterFactory.create(System.out);
    try {
      context.getMessage().writeTo(writer);
    } catch (XMLStreamException e) {
      throw new IllegalStateException("Unable to write");
    }
  } else {
    System.out.println("nInbound message:");
  }
  return true;
}

我试图通过将一个简单的服务放在一起来复制您的问题,该服务接受 MTOM 传输的图像。 我发现如果我在设置处理程序之前放置启用 MTOM 的代码,它会正确编码消息。 如果我先设置处理程序,它不会。 以下是我设置正常运行的客户端代码的地方:

Service service = Service.create(url, qname);
Greeting greeting = service.getPort(Greeting.class);
BindingProvider bp = (BindingProvider) greeting;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
service.setHandlerResolver(new HandlerResolver() {
    @SuppressWarnings("rawtypes")
    public List<Handler> getHandlerChain(PortInfo portInfo) {
        List<Handler> handlerList = new ArrayList<Handler>();
        handlerList.add(new RGBSOAPHandler());
        return handlerList;
    }
});

其中RGBSOAPHandler只是我从另一个 SO 答案中获取的一些示例代码。

编辑:另外,如果我尝试在绑定而不是服务上设置处理程序,那么我会遇到与您相同的问题。 所以如果它看起来像这样:

Service service = Service.create(url, qname);
Greeting greeting = service.getPort(Greeting.class);
BindingProvider bp = (BindingProvider) greeting;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
List<Handler> handlerList = new ArrayList<Handler>();
handlerList.add(new RGBSOAPHandler());
binding.setHandlerChain(handlerList);

然后我的文件被内联编码。 我不知道为什么会这样,但我想答案是"不要那样做"。 在Service对象上设置处理程序。

看起来我受到框架和处理程序工作方式的限制。我认为在这个阶段,我唯一的选择就是去一个较低的水平。我确实看了一下使用管子,但表现出相同的行为,因此看起来任何使用请求的XML的尝试都失败了。因此,我将不得不暂时放弃处理程序,并在较低级别调查我是否可以利用编解码器来完成我所追求的事情。MTOM 实现听起来像是在字节级别做我所追求的事情:

http://jax-ws.java.net/nonav/jax-ws-20-fcs/arch/com/sun/xml/ws/encoding/MtomCodec.html

我想象这会不那么复杂,但会随着我在编解码器方面的进展而更新。

@David:感谢您在处理程序方面的帮助,但看起来似乎没有该级别的解决方案。

更新 1

想出了一个适合我目的的替代解决方案。

  1. 我使用我的 SOAPHandler 对 SOAP 消息的必要部分进行签名。
  2. 编写了一个新的 SOAPHandler,然后获取生成的消息并手动提取错误内联的二进制内容。
  3. 然后,我创建一个AttachmentPart并将步骤 2 中的内容注入其中。它也需要 Base64 编码的文本,这很方便。然后,该AttachmentPart分配了一个用于Content-Id的引用 UUID。
  4. 然后,我创建一个新元素来代替 SOAP 正文中引用 UUID 的 Base64 内容,如下所示:

    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:UUID!!!"></xop:Include> 
    

可能会就此写一篇博客文章,因为到目前为止,这已经是一个史诗般的旅程。这不是最好的解决方案,但它肯定比沿着管子/编解码器路径走下去更容易。

相关内容

  • 没有找到相关文章

最新更新