【问题标题】:How do I sign an MTOM SOAP message using SOAPHandlers?如何使用 SOAPHandlers 签署 MTOM SOAP 消息?
【发布时间】:2012-08-10 07:03:09
【问题描述】:

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

只要我介绍了一个处理程序,MTOM 内容现在就内嵌了。

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

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

关于记录器,它又是一个简单的 SOAPHandler。如果独占使用它或签名处理程序,则结果是相同的,即内联字节内容的 MTOM 消息。我取得的唯一进展是使用 MessageHandler 进行日志记录。这使我能够输出 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 编码,还是仅干扰签名处理程序?
  • 如果仅使用记录器 SOAPHandler 本身会导致问题,请关注此问题。您可以发布该代码吗?下面的答案可以根据需要运行,一个 MTOM 多部分消息(即不是内联),因此您的处理程序代码必须有一些独特的东西。

标签: java java-metro-framework mtom xml-dsig


【解决方案1】:

我试图通过组合一个接受 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 answer 获取的一些示例代码。

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

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 对象上设置您的处理程序。

【讨论】:

  • 我使用几乎相同的代码。在调试发生的情况时,我注意到将应用 MTOM,但客户端应用程序(使用端口)不会使用处理程序解析器。另一个选项是在端口绑定上设置处理程序链。这仍然给我同样的问题,MTOM 已启用,但二进制内容是内联的。
  • 您是否确认所有处理程序设置都是在启用 MTOM 之后进行的?
  • 是的,我做到了。本质上,与上面代码的唯一区别是我没有设置处理程序解析器。相反,我调用binding.setHandlerChain 并直接在binding.setMTOMEnabled(true) 调用之后传入处理程序链。有没有可能this是根本原因?
  • 按照您的方式尝试,遇到了问题。请参阅我的答案的编辑。您的链接似乎与您面临的问题相同。
【解决方案2】:

看起来我受到框架和处理程序工作方式的限制。我认为在这个阶段,我唯一的选择就是去一个较低的水平。我确实看过使用管,但同样的行为表现出来,所以看起来好像任何使用请求的 XML 的尝试都失败了。因此,我将不得不暂时放弃处理程序并在较低级别调查我是否可以利用codecs 来做我想要的事情。一个 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. 然后我创建一个新元素来代替引用 UUID 的 SOAP 主体中的 Base64 内容,如下所示:

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

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

【讨论】:

  • 嘿,我看到你问了这个问题,你回答了这个问题,你把你的回答评为最佳答案!
  • 是的,我相信就解决我遇到的具体问题而言,它是唯一有效的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2021-03-23
  • 1970-01-01
  • 2019-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多