最近作的一个项目,涉及到报文(XML)的加签,验签.加签前要对报文进行规范化.java
须要规范化的缘由:XML格式的报文信息,通常都要转为Document对象进行解析处理,而从对象中解析出的内容颇有可能与另外一方加签时的原内容有出入.如:<Object id="001">若是另外一方加签时,不当心多了个空格<Object id="001" >,而验签时从Document中解析出的内容却没有空格,那么验签确定没法经过的.相似此种格式还有不少,如<input/>与<input><input/>;换行符是\r\n仍是\n?这些若是不统一,加签,验签是几乎没法成功的!spa
所以就须要有统一的标准规范!因为规范方法有多种,实际业务中双方要约定好规范方法!code
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import javax.xml.crypto.OctetStreamData; import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.crypto.dsig.TransformService; public class XmlTest { public static void main(String[] args) throws Exception { byte[] bytes = Files.readAllBytes(Paths.get("E:/HDE_W3C_Message_Sample.xml")); System.out.println(new String(bytes).replaceAll("\r\n", "★\r\n")); System.out.println("---------------------------------------------------"); TransformService ts = TransformService.getInstance(CanonicalizationMethod.INCLUSIVE, "DOM"); String result; try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { OctetStreamData data = new OctetStreamData(bais); OctetStreamData newData = (OctetStreamData) ts.transform(data, null); InputStream is = newData.getOctetStream(); byte[] buf = new byte[1024*1024]; int len = is.read(buf); while (len != -1) { baos.write(buf, 0, len); len = is.read(buf); } result = baos.toString(StandardCharsets.UTF_8.toString()); System.out.println(result.replace("\n", "★\r\n")); } System.out.println("---------------"); } }
上述规范进行的处理有:
1.将全部的\r\n替换为\n;
2.替换无效的空白;如<Object id="001" >中Object与id之间的空白是有效的,而>前面的就是无效的,标签体内容的空白也是有效的
3.标签体为空的统一展开为开始和结束;如<input/>转为<input><input/>
orm
主要涉及到3个类
javax.xml.crypto.OctetStreamData;
javax.xml.crypto.dsig.CanonicalizationMethod;
javax.xml.crypto.dsig.TransformService;xml
javax.xml.crypto.dsig.TransformService; 是用来生成一个转换对象
javax.xml.crypto.dsig.CanonicalizationMethod; 中定义了多个规范化标准方法,都是以URI的方式展示
javax.xml.crypto.OctetStreamData; 存放须要转换的XML内容对象
CanonicalizationMethod 中的规范化方法有如下几种:get
final static String INCLUSIVE = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; final static String INCLUSIVE_WITH_COMMENTS = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"; final static String EXCLUSIVE = "http://www.w3.org/2001/10/xml-exc-c14n#"; final static String EXCLUSIVE_WITH_COMMENTS = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";