Java 如何在SpringWS客户端请求中添加证书链

Java 如何在SpringWS客户端请求中添加证书链,java,spring,ssl-certificate,Java,Spring,Ssl Certificate,我有一个简单的spring ws客户端,它向某个url发送请求: @SuppressWarnings("unchecked") private JAXBElement<O> sendSyncSoapRequest(final JAXBElement<I> req, final String iszrUrl) { if (iszrUrl != null) { return (JAXBElement<O>) this.wsTemplat

我有一个简单的spring ws客户端,它向某个url发送请求:

  @SuppressWarnings("unchecked")
  private JAXBElement<O> sendSyncSoapRequest(final JAXBElement<I> req, final String iszrUrl) {
    if (iszrUrl != null) {
      return (JAXBElement<O>) this.wsTemplate.marshalSendAndReceive(iszrUrl, req);
    } else {
      return (JAXBElement<O>) this.wsTemplate.marshalSendAndReceive(req);
    }
  }
@SuppressWarnings(“未选中”)
私有JAXBElement sendSyncSoapRequest(最终JAXBElement请求,最终字符串iszrUrl){
if(iszrUrl!=null){
返回(JAXBElement)this.wsTemplate.MarshalSendReceive(iszrUrl,req);
}否则{
返回(JAXBElement)this.wsTemplate.MarshalSendReceive(req);
}
}

现在我需要将证书链附加到soap请求。我该怎么做?请帮助

在Spring中,我不知道在客户端上使用证书身份验证有什么语法上的好处。然而,现在我可能错过了一些东西。在没有其他人指出有一个简单的注释可以应用于web服务模板的情况下,我的想法如下

这并不是一个完全循序渐进的答案,但它应该会让你走到这一步。通过使用WebServiceMessageCallback,您可以在发送消息之前修改SOAP消息中的头。下面的代码演示如何将用户名和密码添加到标题中

您应该能够使用相同的机制以类似的方式将证书添加到安全头中。请看下面的文档,该文档解释了基于SOAP证书的身份验证,并在第9页显示了用于此目的的示例安全头

Object response=getWebServiceTemplate().MarshalSendReceive(
公开要求,
新的WebServiceMessageCallback(){
/**
*doWithMessage回调使我们能够在消息返回后修改它
*它是使用漂亮的Spring/JAXB编组构建的,就在
*发出。
*/
@凌驾
公共无效doWithMessage(WebServiceMessage消息)
抛出IOException、TransformerException{
applySecurityHeaders(消息、SOAP\u操作);
}
}
);
/**
*向传出消息添加安全标头,以便客户端
*针对web服务进行身份验证。
*/
私有void applySecurityHeaders(WebServiceMessage消息、字符串soapAction)
抛出IOException、TransformerException{
Assert.isInstanceOf(SoapMessage.class,message);
SoapMessage SoapMessage=(SoapMessage)消息;
soapMessage.setSoapAction(soapAction);
SoapHeader=soapMessage.getSoapHeader();
Transformer Transformer=TransformerFactory.newInstance().newTransformer();
transform(getSecurityHeaderSource(),header.getResult());
writeTo(新的LoggingOutputStream(log));
}
/**
*返回基本SOAP安全标头所需的内容。
*/
私有StringSource getSecurityHeaderSource(){
返回新的字符串源(
“\n”
+“\n”
+“\n”
+“\n”
+“\n”
+“\n”);
}

所以我已经解决了这个问题。我需要使用新的httpClient创建WebServiceMessageSender,其中包含sslFactory和我的证书:

WebServiceMessageSender sender = new HttpComponentsMessageSender(HttpClients.custom()
            .addInterceptorFirst(new RemoveSoapHeadersInterceptor()).setSSLSocketFactory(factory));
wsTemplate.setMessageSender(sender);        


// copy & paste from HttpComponentsMessageSender:
/**
 * HttpClient {@link org.apache.http.HttpRequestInterceptor} implementation that removes {@code Content-Length} and
 * {@code Transfer-Encoding} headers from the request. Necessary, because SAAJ and other SOAP implementations set
 * these headers themselves, and HttpClient throws an exception if they have been set.
 */
public static class RemoveSoapHeadersInterceptor implements HttpRequestInterceptor {



    @Override
    public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
        if (request instanceof HttpEntityEnclosingRequest) {
            if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
                request.removeHeaders(HTTP.TRANSFER_ENCODING);
            }
            if (request.containsHeader(HTTP.CONTENT_LEN)) {
                request.removeHeaders(HTTP.CONTENT_LEN);
            }
        }
    }
}

若服务使用WS-Security,我建议使用一些SOAP库,例如,它设计用于使用WS-Security。如果服务使用某种自定义实现,则它取决于实现。在这种情况下,将服务wsdl添加到问题中,也许有人会帮助您。请检查
HttpComponentsMessageSender
和Apache HTTP组件提供的可能性。
WebServiceMessageSender sender = new HttpComponentsMessageSender(HttpClients.custom()
            .addInterceptorFirst(new RemoveSoapHeadersInterceptor()).setSSLSocketFactory(factory));
wsTemplate.setMessageSender(sender);        


// copy & paste from HttpComponentsMessageSender:
/**
 * HttpClient {@link org.apache.http.HttpRequestInterceptor} implementation that removes {@code Content-Length} and
 * {@code Transfer-Encoding} headers from the request. Necessary, because SAAJ and other SOAP implementations set
 * these headers themselves, and HttpClient throws an exception if they have been set.
 */
public static class RemoveSoapHeadersInterceptor implements HttpRequestInterceptor {



    @Override
    public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
        if (request instanceof HttpEntityEnclosingRequest) {
            if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
                request.removeHeaders(HTTP.TRANSFER_ENCODING);
            }
            if (request.containsHeader(HTTP.CONTENT_LEN)) {
                request.removeHeaders(HTTP.CONTENT_LEN);
            }
        }
    }
}