我已经实现了一个spring-ws(2.0.2)服务,它需要soap标头中的一些自定义元素。我正在尝试使用Spring的MockWebServiceClient生成一个有效的请求来测试调度程序,marshallers等。
我得到的问题是MockWebSerivce似乎只支持Soap Body(有效载荷)。
如何访问正在生成的soap请求以获取正确的标头?
如果除了Spring的MockWebServiceClient之外还有一个更好的库来执行此操作,那也没关系。
相关链接:
http://forum.springsource.org/showthread.php?101708-MockWebServiceClient-amp-WS-Security
Add SoapHeader to org.springframework.ws.WebServiceMessage
答案 0 :(得分:2)
当我想用安全性测试spring web服务时遇到了类似的问题,我最终使用Spring Interceptors在它们到达终点之前修改了标头,我启用了拦截器仅用于测试。
创建一个拦截器,我实现了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服务。
答案 1 :(得分:0)
我确实找到了做我真正想要的smock库:只需要一个包含整个请求的文本文件。
http://code.google.com/p/smock/wiki/SpringWs
它支持与弹簧提供的相同的请求和响应匹配器。它还使我的测试非常独立。 (而不是仅在我的测试用例中使用的全新类。)
答案 2 :(得分:0)
如您所述,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响应(标头和正文)。