Canonicalize XML in Java

  sonic0002        2016-01-20 01:39:45       18,989        0          English  简体中文  繁体中文  ภาษาไทย  Tiếng Việt 

Việc chuẩn hóa XML thường được sử dụng khi cần tạo chữ ký số để gửi cho các bên ngang hàng để xác minh. Vì chữ ký số được tạo dựa trên dữ liệu XML, dữ liệu XML phải được chuẩn hóa trước khi có thể tính toán giá trị chữ ký của nó. Ngay cả một khoảng trắng thừa cũng có thể ảnh hưởng đến giá trị chữ ký được tính toán, do đó, nó phải tuân theo một số quy tắc để chuẩn hóa dữ liệu XML để nó có định dạng tiêu chuẩn. Đây là lý do tại sao W3C tạo ra đặc tả Canonical XML Version 1.1.

Đặc tả này cung cấp các quy tắc để định dạng các nút phần tử, nút thuộc tính và nút không gian tên, v.v. Các ngôn ngữ lập trình khác nhau đã triển khai đặc tả này để chúng ta có thể sử dụng chúng để chuẩn hóa dữ liệu XML một cách dễ dàng mà không cần biết chi tiết về đặc tả.

Trong hướng dẫn này, chúng ta sẽ không đi vào chi tiết về đặc tả, chúng ta sẽ chỉ tập trung vào cách gọi API Java để chuẩn hóa dữ liệu XML. Dựa trên mô hình dữ liệu XPath, một Tài liệu XML được biểu diễn bằng một tập hợp các nút -- tập hợp nút. Trong khi API XML trong Java nhận một đối tượng Dữ liệu cần được chuẩn hóa. Để minh họa việc chuẩn hóa, chúng ta sẽ tạo một NodeSetDataImpl tùy chỉnh triển khai các giao diện NodeSetData và Iterator. 

import java.util.Iterator;
import javax.xml.crypto.NodeSetData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.NodeIterator;

public class NodeSetDataImpl implements NodeSetData, Iterator {
	private Node ivNode;
	private NodeFilter ivNodeFilter;
	private Document ivDocument;
	private DocumentTraversal ivDocumentTraversal;
	private NodeIterator ivNodeIterator;
	private Node ivNextNode;

	public NodeSetDataImpl(Node pNode, NodeFilter pNodeFilter) throws Exception {
		ivNode = pNode;
		ivNodeFilter = pNodeFilter;

		if (ivNode instanceof Document) {
			ivDocument = (Document) ivNode;
		} else {
			ivDocument = ivNode.getOwnerDocument();
		}

		ivDocumentTraversal = (DocumentTraversal) ivDocument;
	}

	private NodeSetDataImpl(NodeIterator pNodeIterator) {
		ivNodeIterator = pNodeIterator;
	}

	public Iterator iterator() {
		NodeIterator nodeIterator = ivDocumentTraversal.createNodeIterator(ivNode, NodeFilter.SHOW_ALL, ivNodeFilter, false);
		return new NodeSetDataImpl(nodeIterator);
	}

	private Node checkNextNode() {
		if (ivNextNode == null && ivNodeIterator != null) {
			ivNextNode = ivNodeIterator.nextNode();
			if (ivNextNode == null) {
				ivNodeIterator.detach();
				ivNodeIterator = null;
			}
		}
		return ivNextNode;
	}

	private Node consumeNextNode() {
		Node nextNode = checkNextNode();
		ivNextNode = null;
		return nextNode;
	}

	public boolean hasNext() {
		return checkNextNode() != null;
	}

	public Node next() {
		return consumeNextNode();
	}

	public void remove() {
		throw new UnsupportedOperationException("Removing nodes is not supported.");
	}

	public static NodeFilter getRootNodeFilter() {
		return new NodeFilter() {
			public short acceptNode(Node pNode) {
				if (pNode instanceof Element && pNode.getParentNode() instanceof Document) {
					return NodeFilter.FILTER_SKIP;
				}
				return NodeFilter.FILTER_ACCEPT;
			}
		};
	}
}

Sau đó, chúng ta cần tạo một CanonicalizationMethod để thực hiện việc chuẩn hóa thực tế. Có một vài lựa chọn ở đây:

CanonicalizationMethod.INCLUSIVE
CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS
CanonicalizationMethod.EXCLUSIVE
CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS

Trong hướng dẫn này, chúng ta sẽ chỉ minh họa việc chuẩn hóa bao gồm. Dưới đây là mã để thực hiện việc này.

import java.io.ByteArrayInputStream;
import javax.xml.crypto.Data;
import javax.xml.crypto.OctetStreamData;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

public class CanonicalizationTest {
	private static String INPUT = 
			"" +
			"hello" +
			"world" +
			"";
	
	public static void main(String[] args){
		transform(INPUT);
	}
	
	/**
	 * Create new document with data
	 * 
	 * @param xml
	 * @return
	 */
	private static Document createNewDocument(String xml){
		try{
			byte[] bytes = xml.getBytes("UTF-8");
			ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
			
			DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
			fac.setNamespaceAware(true);
			
			DocumentBuilder docBuilder = fac.newDocumentBuilder();
			
			Document doc = docBuilder.parse(bin);

			return doc;
		} catch (Exception ex){
			ex.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Transform a XML string
	 * 
	 * @param xml
	 */
	private static void transform(String xml){
		Document doc = createNewDocument(xml);
		
		try{
			Data data = new NodeSetDataImpl(doc, NodeSetDataImpl.getRootNodeFilter());
			XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
			CanonicalizationMethod canonicalizationMethod = fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null);
			// Doing the actual canonicalization
			OctetStreamData transformedData =(OctetStreamData) canonicalizationMethod.transform(data, null);
			byte[] bytes = tool.Util.readStream(transformedData.getOctetStream());
			String str = new String(bytes);
			System.out.println(str);
		} catch (Exception ex){
			ex.printStackTrace();
		}
	}
}

Đầu tiên, hãy xem đầu ra:

<my:Node xmlns:my="http://example.com" Id="1">hello</my:Node><my:Node xmlns:my="http://example.com" Id="2">world</my:Node>

Thử nghiệm sẽ tạo một Tài liệu trước và sau đó Tài liệu này sẽ được chuyển đến NodeSetDataImpl để tạo tập hợp nút cần được chuẩn hóa. Từ đầu ra, chúng ta có thể thấy rằng nút Root bị xóa trong dữ liệu đã được chuẩn hóa, điều này là do NodeFilter trong NodeSetDataImpl đã lọc nút này. Tiếp theo, my:Node thứ hai có nút xmlns:my trước nút Id ở dạng chuẩn hóa. Điều này dựa trên đặc tả Canonical XML, trong đó các nút phải theo thứ tự từ vựng.

Đối với các phương pháp chuẩn hóa khác, logic ở đây là giống nhau. Sự khác biệt là đầu ra không giống nhau vì các phương pháp chuẩn hóa khác nhau có các quy tắc khác nhau.

JAVA  JAVA SECURITY  XML 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Search answer on Google