如何测试需要soapHeaders的Spring-WS Web服务?

发布于 2024-12-02 02:50:36 字数 678 浏览 1 评论 0原文

我已经实现了一个 spring-ws (2.0.2) 服务,它需要肥皂头中的一些自定义元素。我正在尝试使用 Spring 的 MockWebServiceClient 生成有效的请求来测试调度程序、编组器等。

我遇到的问题是 MockWebSerivce 似乎只支持 Soap Body(有效负载)。

如何访问正在生成的肥皂请求以将正确的标头放入其中?

如果除了 Spring 的 MockWebServiceClient 之外还有一个更好的库可以做到这一点,那也很好。

相关链接: http://forum.springsource.org/showthread.php? 101708-MockWebServiceClient-amp-WS-Security
将 SoapHeader 添加到 org.springframework.ws.WebServiceMessage

I have a spring-ws (2.0.2) service I have implemented that requires some custom elements in the soap header. I am trying to use Spring's MockWebServiceClient to generate a valid request to test the dispatcher, marshallers, etc.

The problem I am getting is that the MockWebSerivce only seems to support the Soap Body (the payload).

How can I access the soap request being generated to get the right headers into it?

If there is a better library for doing this other than Spring's MockWebServiceClient, that would be fine too.

Related Links:
http://forum.springsource.org/showthread.php?101708-MockWebServiceClient-amp-WS-Security
Add SoapHeader to org.springframework.ws.WebServiceMessage

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

a√萤火虫的光℡ 2024-12-09 02:50:36

当我想使用安全性测试 Spring Web 服务时,我遇到了类似的问题,我最终使用 Spring 拦截器在到达终点之前修改标头,我启用拦截器仅用于测试。

创建一个拦截器,我实现了 SmartEndpointInterceptor,如果您选择

public class ModifySoapHeaderInterceptor implements
    SmartEndpointInterceptor 
{
  //WSConstants.WSSE_NS;
   private static final String DEFAULT_SECURITY_URL = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    private static final String SECURITY_TAG = "Security";
    private static final String SECURITY_PREFIX = "wsse";
    private static final String USER_NAME_TOKEN = "UsernameToken";

    @Override
public boolean handleRequest(MessageContext messageContext, Object endpoint)
        throws Exception 
{
      SaajSoapMessage saajSoapMessage(SaajSoapMessage)messageContext.getRequest());
      SOAPHeader soapHeader = saajSoapMessage.getSaajMessage().getSOAPPart()
            .getEnvelope().getHeader();

       //you can modify header's as you choose
       Name headerElement = saajSoapMessage.getSaajMessage().getSOAPPart()
            .getEnvelope()
            .createName(SECURITY_TAG, SECURITY_PREFIX, DEFAULT_SECURITY_URL);
       SOAPHeaderElement soapHeaderElement = soapHeader
            .addHeaderElement(headerElement);
    SOAPElement usernameToken = soapHeaderElement.addChildElement(
            USER_NAME_TOKEN, SECURITY_PREFIX);

    SOAPElement userNameElement = usernameToken.addChildElement("Username",
            SECURITY_PREFIX);
    userNameElement.addTextNode("userid");//you can inject via spring

    SOAPElement passwordElement = usernameToken.addChildElement("Password",
            SECURITY_PREFIX);
    passwordElement.addTextNode("password");
       return true;
    }
}

在 spring 上下文中配置此拦截器,

  <sws:interceptors>
     <bean class="prasanna.ws.security.wss4j.ModifySoapHeaderInterceptor"/>
  </sws:interceptors>

您可以使用其他拦截器这将在消息到达终点之前向消息添加必要的安全标头,您仍然可以使用 MockWebServiceClient 来测试您的 Web服务。

I had the similar problem when I wanted to test spring web service with Security, I ended up using the Spring Interceptors to modify the header before they reach end point, I enabled the interceptors only for testing.

Create an interceptor, I implemented the SmartEndpointInterceptor, You can use the other interceptors if you choose

public class ModifySoapHeaderInterceptor implements
    SmartEndpointInterceptor 
{
  //WSConstants.WSSE_NS;
   private static final String DEFAULT_SECURITY_URL = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    private static final String SECURITY_TAG = "Security";
    private static final String SECURITY_PREFIX = "wsse";
    private static final String USER_NAME_TOKEN = "UsernameToken";

    @Override
public boolean handleRequest(MessageContext messageContext, Object endpoint)
        throws Exception 
{
      SaajSoapMessage saajSoapMessage(SaajSoapMessage)messageContext.getRequest());
      SOAPHeader soapHeader = saajSoapMessage.getSaajMessage().getSOAPPart()
            .getEnvelope().getHeader();

       //you can modify header's as you choose
       Name headerElement = saajSoapMessage.getSaajMessage().getSOAPPart()
            .getEnvelope()
            .createName(SECURITY_TAG, SECURITY_PREFIX, DEFAULT_SECURITY_URL);
       SOAPHeaderElement soapHeaderElement = soapHeader
            .addHeaderElement(headerElement);
    SOAPElement usernameToken = soapHeaderElement.addChildElement(
            USER_NAME_TOKEN, SECURITY_PREFIX);

    SOAPElement userNameElement = usernameToken.addChildElement("Username",
            SECURITY_PREFIX);
    userNameElement.addTextNode("userid");//you can inject via spring

    SOAPElement passwordElement = usernameToken.addChildElement("Password",
            SECURITY_PREFIX);
    passwordElement.addTextNode("password");
       return true;
    }
}

Configure this interceptor in spring context

  <sws:interceptors>
     <bean class="prasanna.ws.security.wss4j.ModifySoapHeaderInterceptor"/>
  </sws:interceptors>

This will add the necessary security headers to the message before it reaches the end point, You can still use MockWebServiceClient to test your web service.

故笙诉离歌 2024-12-09 02:50:36

正如您所指出的,MockWebServiceClient sendRequest() 方法仅使用给定的有效负载设置 SOAP 主体。它不触及 SOAP 标头。

要设置 SOAP 标头,您可以创建一个实现 RequestCreator 接口并设置 SOAP 标头的类。将此类的实例传递给 sendRequest() 方法。

例如:

class SoapActionCreator implements RequestCreator {

    private final Source payload;

    public SoapActionCreator(Source payload) {
        this.payload = payload;
    }

    @Override
    public WebServiceMessage createRequest(WebServiceMessageFactory webServiceMessageFactory)
            throws IOException {
        WebServiceMessage webServiceMessage =
                new PayloadMessageCreator(payload).createMessage(webServiceMessageFactory);

        SoapMessage soapMessage = (SoapMessage) webServiceMessage;
        SoapHeader header = soapMessage.getSoapHeader();
        // Add an Action element to the SOAP header
        StringSource headerSource = new StringSource(
                "<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">https://example.com/foo/bar</wsa:Action>");
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.transform(headerSource, header.getResult());

        return webServiceMessage;
    }

}

然后像这样使用 SoapActionCreator

    SoapActionCreator soapActionCreator = new SoapActionCreator(requestPayload);
    mockClient.sendRequest(soapActionCreator).
            andExpect(payload(responsePayload));

其中 requestPayload 是 SOAP 请求正文,responsePayload 是整个 SOAP 响应(标头和正文) 。

As you noted, the MockWebServiceClient sendRequest() method only sets up the SOAP body with the payload given it. It does not touch the SOAP header.

To set up the SOAP header as well you can create a class that implements the RequestCreator interface and sets the SOAP header. Pass an instance of this class to the sendRequest() method.

For example:

class SoapActionCreator implements RequestCreator {

    private final Source payload;

    public SoapActionCreator(Source payload) {
        this.payload = payload;
    }

    @Override
    public WebServiceMessage createRequest(WebServiceMessageFactory webServiceMessageFactory)
            throws IOException {
        WebServiceMessage webServiceMessage =
                new PayloadMessageCreator(payload).createMessage(webServiceMessageFactory);

        SoapMessage soapMessage = (SoapMessage) webServiceMessage;
        SoapHeader header = soapMessage.getSoapHeader();
        // Add an Action element to the SOAP header
        StringSource headerSource = new StringSource(
                "<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">https://example.com/foo/bar</wsa:Action>");
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.transform(headerSource, header.getResult());

        return webServiceMessage;
    }

}

Then use SoapActionCreator like this:

    SoapActionCreator soapActionCreator = new SoapActionCreator(requestPayload);
    mockClient.sendRequest(soapActionCreator).
            andExpect(payload(responsePayload));

where requestPayload is the SOAP request body and responsePayload is the entire SOAP response (header and body).

傻比既视感 2024-12-09 02:50:36

我确实找到了工作服库,它可以实现我真正想要的功能:只需要一个包含整个请求的文本文件。

http://code.google.com/p/smock/wiki/SpringWs

它支持与 spring 提供的内容相同的请求和响应匹配器。它还使我的测试非常独立。 (而不是仅在我的测试用例中使用的全新类。)

I did find the smock library which does what I really wanted: just takes a text file with the whole request in it.

http://code.google.com/p/smock/wiki/SpringWs

It supports the same request and response matchers as the spring provided stuff. It also keeps my tests very self contained. (Rather than a whole new class that would only be used in my test cases.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文