如何生成部分XML签名(即SignedInfo标签内容)并封装为SOAP请求
类转换异常原因
你遇到的类转换错误是类加载冲突导致:JDK内置的XML DSIG实现和Apache Santuario库的DOMSignedInfo类全限定名高度相似,但属于不同的类加载源,完全不需要做这个强转操作,XMLSignatureFactory本身已经提供了官方序列化方法。
解决步骤
1. 准备空白DOM文档
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 必须开启命名空间感知 dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().newDocument();
2. 直接序列化SignedInfo到DOM节点
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); // 沿用你已有逻辑构造SignedInfo对象 SignedInfo si = fac.newSignedInfo(/* 你原有构造参数,包含已计算好的摘要、转换规则等 */); // 直接调用marshal方法序列化,指定命名空间前缀为ds fac.marshal(si, doc, "ds"); // 此时doc的根节点就是完整的<ds:SignedInfo>节点 Element signedInfoElement = doc.getDocumentElement();
3. 转换为XML字符串并封装为目标结构
将DOM节点转为字符串后,即可按需封装到SOAP信封的CDATA节点中:
TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); // 可选配置:省略XML声明、开启格式化缩进 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter sw = new StringWriter(); transformer.transform(new DOMSource(signedInfoElement), new StreamResult(sw)); String signedInfoXml = sw.toString();
后续你可以选择直接拼接字符串生成完整的SOAP结构,也可以用DOM生成完整SOAP信封,将signedInfoXml写入<signature>节点下的CDATA节点即可。
注意事项
- 构造SignedInfo时指定的
SignatureMethod算法需要和签名服务使用的算法保持一致 - 序列化前需要确保所有
Reference的DigestValue已经完成计算并填充 - 如果需要外层包裹
<ds:Signature>根节点,只需要提前在空白DOM中创建该节点作为父节点,调用marshal时传入该父节点即可
内容的提问来源于stack exchange,提问作者Val Bonn
相关产品推荐
相关产品推荐

