You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求带签名的SOAP请求完整Java代码(含导入及Maven依赖)

带WS-Security签名的SOAP请求完整实现

一、Maven依赖配置

添加必要依赖,基于Apache CXF实现WS-Security,BouncyCastle提供加密支持:

<dependencies>
    <!-- Apache CXF SOAP核心模块 -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.6.4</version>
    </dependency>
    <!-- CXF WS-Security安全模块 -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-ws-security</artifactId>
        <version>3.6.4</version>
    </dependency>
    <!-- BouncyCastle加密算法库 -->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.70</version>
    </dependency>
    <!-- XML处理工具依赖 -->
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
</dependencies>

二、完整Java代码

以下代码包含XML读取、WS-Security签名/解密配置、SOAP请求发送,同时解决你遇到的XML解析显示[#document:null]的问题:

import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

// 替换为实际SOAP服务生成的接口(可通过CXF wsdl2java工具生成)
interface SoapService {
    String sendRequest(String xmlRequest);
}

public class SignedSoapClient {
    // 密钥库配置参数,替换为实际值
    private static final String KEYSTORE_PATH = "C:\\Certificates\\Cert.jks";
    private static final String KEYSTORE_PWD = "your-keystore-password";
    private static final String CERT_ALIAS = "TestCert";
    private static final String PRIVATE_KEY_PWD = "your-private-key-password";

    public static void main(String[] args) throws Exception {
        // 1. 读取并解析XML请求文件(解决[#document:null]问题)
        Document requestDoc = readXmlFile("C:\\path\\to\\your\\request.xml");
        String xmlRequest = convertDocToString(requestDoc);
        System.out.println("解析后的XML请求:\n" + xmlRequest);

        // 2. 创建CXF客户端代理
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setAddress("https://your-soap-service-endpoint.com");
        factory.setServiceClass(SoapService.class);
        SoapService service = (SoapService) factory.create();
        Client client = ClientProxy.getClient(service);

        // 3. 配置出站WS-Security(签名)
        Map<String, Object> outSecurityProps = new HashMap<>();
        outSecurityProps.put("action", "Signature Timestamp");
        // 签名核心配置
        outSecurityProps.put("signatureKeyIdentifier", "DirectReference");
        outSecurityProps.put("signatureUser", CERT_ALIAS);
        outSecurityProps.put("signaturePassword", PRIVATE_KEY_PWD);
        outSecurityProps.put("signatureKeystore", KEYSTORE_PATH);
        outSecurityProps.put("signatureStorePassword", KEYSTORE_PWD);
        // 算法配置
        outSecurityProps.put("signatureAlgorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512");
        outSecurityProps.put("signatureCanonicalization", "http://www.w3.org/2001/10/xml-exc-c14n#");
        outSecurityProps.put("signatureDigestAlgorithm", "http://www.w3.org/2001/04/xmlenc#sha512");
        // 签名TimeStamp元素
        outSecurityProps.put("signatureParts", "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");

        // 添加出站拦截器
        client.getOutInterceptors().add(new SAAJOutInterceptor());
        client.getOutInterceptors().add(new WSS4JOutInterceptor(outSecurityProps));

        // 4. 配置入站WS-Security(解密)
        Map<String, Object> inSecurityProps = new HashMap<>();
        inSecurityProps.put("action", "Decrypt");
        inSecurityProps.put("decryptKeystore", KEYSTORE_PATH);
        inSecurityProps.put("decryptStorePassword", KEYSTORE_PWD);
        inSecurityProps.put("decryptPassword", PRIVATE_KEY_PWD);

        client.getInInterceptors().add(new WSS4JInInterceptor(inSecurityProps));

        // 5. 发送请求并输出响应
        String response = service.sendRequest(xmlRequest);
        System.out.println("服务响应:\n" + response);
    }

    // 读取XML文件为Document对象
    private static Document readXmlFile(String filePath) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true); // 必须启用命名空间支持,避免解析异常
        DocumentBuilder builder = factory.newDocumentBuilder();
        return builder.parse(new File(filePath));
    }

    // 将Document转换为字符串(解决直接打印显示[#document:null]的问题)
    private static String convertDocToString(Document doc) throws Exception {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        StringWriter writer = new StringWriter();
        transformer.transform(new DOMSource(doc), new StreamResult(writer));
        return writer.getBuffer().toString();
    }
}

三、关键配置对应说明

出站签名配置

  • 密钥库:通过signatureKeystore指定C:\Certificates\Cert.jks路径
  • 别名:signatureUser设置为TestCert
  • 密钥标识符类型:signatureKeyIdentifier设为DirectReference(对应Binary Security Token)
  • 签名算法:signatureAlgorithm使用http://www.w3.org/2001/04/xmldsig-more#rsa-sha512(即rs-sha512)
  • 签名规范化:signatureCanonicalization使用http://www.w3.org/2001/10/xml-exc-c14n#(即xml-exc-c14n#)
  • 摘要算法:signatureDigestAlgorithm使用http://www.w3.org/2001/04/xmlenc#sha512(即xmlenc#sha512)
  • 签名部分:signatureParts指定签名TimeStamp元素
  • 单一证书:默认使用指定别名的单一证书,无需额外配置

入站解密配置

  • 解密密钥库:通过decryptKeystore指定C:\Certificates\Cert.jks路径

四、XML解析问题解决

你之前得到[#document:null]是因为直接打印Document对象的toString()结果,该方法不会输出XML内容。使用上述代码中的convertDocToString()方法,将Document转换为字符串即可查看完整XML内容。同时解析时需启用setNamespaceAware(true),避免因命名空间缺失导致后续签名失败。

内容的提问来源于stack exchange,提问作者Pradeep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 00:06:24