You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ni...@apache.org on 2014/09/16 14:21:54 UTC
git commit: CAMEL-7802 XML Signature: parameter for output character
encoding and parent node via XPath with thanks to Franz
Repository: camel
Updated Branches:
refs/heads/master 0d94bfe0c -> b8ca2bac1
CAMEL-7802 XML Signature: parameter for output character encoding and parent node via XPath with thanks to Franz
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b8ca2bac
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b8ca2bac
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b8ca2bac
Branch: refs/heads/master
Commit: b8ca2bac1d4003140db0283ee4da7788572e844f
Parents: 0d94bfe
Author: Willem Jiang <wi...@gmail.com>
Authored: Tue Sep 16 20:20:58 2014 +0800
Committer: Willem Jiang <wi...@gmail.com>
Committed: Tue Sep 16 20:21:33 2014 +0800
----------------------------------------------------------------------
.../xmlsecurity/XmlSignatureEndpoint.java | 10 +
.../xmlsecurity/XmlSignerEndpoint.java | 8 +
.../api/DefaultXmlSignature2Message.java | 14 +-
.../xmlsecurity/api/XmlSignature2Message.java | 10 +-
.../xmlsecurity/api/XmlSignatureHelper.java | 109 ++++++--
.../processor/XmlSignatureConfiguration.java | 17 ++
.../processor/XmlSignerConfiguration.java | 42 ++-
.../processor/XmlSignerProcessor.java | 75 ++++--
.../processor/XmlVerifierProcessor.java | 6 +
.../xmlsecurity/ECDSASignatureTest.java | 2 +-
.../xmlsecurity/SpringXmlSignatureTest.java | 27 ++
.../component/xmlsecurity/XmlSignatureTest.java | 253 +++++++++++++++++--
.../xmlsecurity/SpringXmlSignatureTests.xml | 16 ++
13 files changed, 510 insertions(+), 79 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignatureEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignatureEndpoint.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignatureEndpoint.java
index 9bec535..3633f04 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignatureEndpoint.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignatureEndpoint.java
@@ -101,5 +101,15 @@ public abstract class XmlSignatureEndpoint extends DefaultEndpoint {
public void setSchemaResourceUri(String schemaResourceUri) {
getConfiguration().setSchemaResourceUri(schemaResourceUri);
+
}
+
+ public String getOutputXmlEncoding() {
+ return getConfiguration().getOutputXmlEncoding();
+ }
+
+ public void setOutputXmlEncoding(String encoding) {
+ getConfiguration().setOutputXmlEncoding(encoding);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignerEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignerEndpoint.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignerEndpoint.java
index 26fd77a..6b67e92 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignerEndpoint.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/XmlSignerEndpoint.java
@@ -184,5 +184,13 @@ public class XmlSignerEndpoint extends XmlSignatureEndpoint {
public void setSignatureId(String signatureId) {
getConfiguration().setSignatureId(signatureId);
}
+
+ public XPathFilterParameterSpec getParentXpath() {
+ return getConfiguration().getParentXpath();
+ }
+
+ public void setParentXpath(XPathFilterParameterSpec parentXpath) {
+ getConfiguration().setParentXpath(parentXpath);
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/DefaultXmlSignature2Message.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/DefaultXmlSignature2Message.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/DefaultXmlSignature2Message.java
index e11c89f..0e3a437 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/DefaultXmlSignature2Message.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/DefaultXmlSignature2Message.java
@@ -17,7 +17,6 @@
package org.apache.camel.component.xmlsecurity.api;
import java.io.ByteArrayOutputStream;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -29,9 +28,6 @@ import javax.xml.crypto.dsig.XMLObject;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.spec.XPathFilterParameterSpec;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
@@ -40,10 +36,12 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
/**
* Maps the XML signature to a camel message. A output node is determined from
* the XML signature document via a node search and then serialized and set to
@@ -194,13 +192,17 @@ public class DefaultXmlSignature2Message implements XmlSignature2Message {
}
protected void transformNodeToByteArrayAndSetToOutputMessage(Input input, Message output, Node node)
- throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException, IOException {
+ throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
- XmlSignatureHelper.transformToOutputStream(node, os, omitXmlDeclaration(output, input));
+ XmlSignatureHelper.transformToOutputStream(node, os, omitXmlDeclaration(output, input), input.getOutputXmlEncoding());
output.setBody(os.toByteArray());
+ if (input.getOutputXmlEncoding() != null) {
+ output.setHeader(Exchange.CHARSET_NAME, input.getOutputXmlEncoding());
+ }
}
+
protected Node getOutputNodeViaXPath(Input input) throws Exception { //NOPMD
checkSearchValueNotNull(input);
checkSearchValueOfType(XPathFilterParameterSpec.class, input);
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignature2Message.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignature2Message.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignature2Message.java
index 6048156..c5e8149 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignature2Message.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignature2Message.java
@@ -22,7 +22,6 @@ import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.XMLObject;
import org.w3c.dom.Document;
-
import org.apache.camel.Message;
/**
@@ -89,6 +88,15 @@ public interface XmlSignature2Message {
* the document set to the output message.
*/
Boolean getRemoveSignatureElements();
+
+ /**
+ * The character encoding of the resulting XML document. Can be
+ * <code>null</code>. If <code>null</code> then the encoding of the
+ * original XML document is used.
+ *
+ */
+ String getOutputXmlEncoding();
+
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureHelper.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureHelper.java
index 2593e3b..6111457 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureHelper.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/api/XmlSignatureHelper.java
@@ -39,14 +39,6 @@ import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
@@ -56,6 +48,10 @@ import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.SAXException;
import org.apache.camel.util.IOHelper;
@@ -66,7 +62,7 @@ import org.apache.camel.util.IOHelper;
*/
public final class XmlSignatureHelper {
private XmlSignatureHelper() {
- //Helper class
+ // Helper class
}
/**
@@ -162,7 +158,7 @@ public final class XmlSignatureHelper {
namespaceMap);
return params;
}
-
+
public static XPathFilterParameterSpec getXpathFilter(String xpath) {
return getXpathFilter(xpath, null);
}
@@ -332,7 +328,7 @@ public final class XmlSignatureHelper {
* @throws Exception
* if an error during the reading of the XSL file occurs
*/
- public static AlgorithmMethod getXslTransform(String path) throws Exception {
+ public static AlgorithmMethod getXslTransform(String path) throws Exception { //NOPMD
InputStream is = readXslTransform(path);
if (is == null) {
throw new IllegalStateException(String.format("XSL file %s not found", path));
@@ -368,7 +364,7 @@ public final class XmlSignatureHelper {
return transformXslt;
}
- protected static InputStream readXslTransform(String path) throws Exception {
+ protected static InputStream readXslTransform(String path) throws Exception { //NOPMD
if (path == null) {
throw new IllegalArgumentException("path is null");
}
@@ -402,8 +398,7 @@ public final class XmlSignatureHelper {
return newDocumentBuilder(disallowDoctypeDecl, null);
}
- public static DocumentBuilder newDocumentBuilder(Boolean disallowDoctypeDecl, Schema schema)
- throws ParserConfigurationException {
+ public static DocumentBuilder newDocumentBuilder(Boolean disallowDoctypeDecl, Schema schema) throws ParserConfigurationException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(false);
@@ -421,8 +416,22 @@ public final class XmlSignatureHelper {
return dbf.newDocumentBuilder();
}
- public static void transformToOutputStream(Node node, OutputStream os, boolean omitXmlDeclaration)
- throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException, IOException {
+ public static void transformToOutputStream(Node node, OutputStream os, boolean omitXmlDeclaration, String encoding) throws Exception { //NOPMD
+
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ byte[] bytes = tranformTextNodeToByteArray(node, encoding);
+ os.write(bytes);
+ } else {
+ transformNonTextNodeToOutputStream(node, os, omitXmlDeclaration, encoding);
+ }
+ }
+
+ /**
+ * Use {@link #transformToOutputStream(Node, OutputStream, boolean, String)}
+ * instead.
+ */
+ @Deprecated
+ public static void transformToOutputStream(Node node, OutputStream os, boolean omitXmlDeclaration) throws Exception { //NOPMD
if (node.getNodeType() == Node.TEXT_NODE) {
byte[] bytes = tranformTextNodeToByteArray(node);
@@ -432,24 +441,74 @@ public final class XmlSignatureHelper {
}
}
- public static void transformNonTextNodeToOutputStream(Node node, OutputStream os, boolean omitXmlDeclaration)
- throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException {
+ /**
+ * Use
+ * {@link #transformNonTextNodeToOutputStream(Node, OutputStream, boolean, String)}
+ * instead.
+ */
+ @Deprecated
+ public static void transformNonTextNodeToOutputStream(Node node, OutputStream os, boolean omitXmlDeclaration) throws Exception { //NOPMD
+ transformNonTextNodeToOutputStream(node, os, omitXmlDeclaration, null);
+ }
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer trans = tf.newTransformer();
- if (omitXmlDeclaration) {
- trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ /**
+ * Serializes a node using a certain character encoding.
+ *
+ * @param node
+ * DOM node to serialize
+ * @param os
+ * output stream, to which the node is serialized
+ * @param omitXmlDeclaration
+ * indicator whether to omit the XML declaration or not
+ * @param encoding
+ * character encoding, can be <code>null</code>, if
+ * <code>null</code> then "UTF-8" is used
+ * @throws Exception
+ */
+ public static void transformNonTextNodeToOutputStream(Node node, OutputStream os, boolean omitXmlDeclaration, String encoding)
+ throws Exception { //NOPMD
+ // previously we used javax.xml.transform.Transformer, however the JDK xalan implementation did not work correctly with a specified encoding
+ // therefore we switched to DOMImplementationLS
+ if (encoding == null) {
+ encoding = "UTF-8";
}
- trans.transform(new DOMSource(node), new StreamResult(os));
+ DOMImplementationRegistry domImplementationRegistry = DOMImplementationRegistry.newInstance();
+ DOMImplementationLS domImplementationLS = (DOMImplementationLS) domImplementationRegistry.getDOMImplementation("LS");
+ LSOutput lsOutput = domImplementationLS.createLSOutput();
+ lsOutput.setEncoding(encoding);
+ lsOutput.setByteStream(os);
+ LSSerializer lss = domImplementationLS.createLSSerializer();
+ lss.getDomConfig().setParameter("xml-declaration", !omitXmlDeclaration);
+ lss.write(node, lsOutput);
}
+ /** use {@link #tranformTextNodeToByteArray(Node, String)} instead. */
+ @Deprecated
public static byte[] tranformTextNodeToByteArray(Node node) {
+ return tranformTextNodeToByteArray(node, null);
+ }
+
+ /**
+ * Trannsforms a text node to byte array using a certain character encoding.
+ *
+ * @param node
+ * text node
+ * @param encoding
+ * character encoding, can be <code>null</code>, if
+ * <code>null</code> then UTF-8 is used
+ * @return byte array, <code>null</code> if the node has not text content
+ * @throws IllegalStateException
+ * if the encoding is not supported
+ */
+ public static byte[] tranformTextNodeToByteArray(Node node, String encoding) {
+ if (encoding == null) {
+ encoding = "UTF-8";
+ }
String text = node.getTextContent();
if (text != null) {
try {
- return text.getBytes("UTF-8");
+ return text.getBytes(encoding);
} catch (UnsupportedEncodingException e) {
- // should not happen
throw new IllegalStateException(e);
}
} else {
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignatureConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignatureConfiguration.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignatureConfiguration.java
index bc67c5a..b752e0a 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignatureConfiguration.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignatureConfiguration.java
@@ -44,6 +44,8 @@ public abstract class XmlSignatureConfiguration implements Cloneable, CamelConte
private Boolean clearHeaders = Boolean.TRUE;
private String schemaResourceUri;
+
+ private String outputXmlEncoding;
public XmlSignatureConfiguration() {
}
@@ -177,5 +179,20 @@ public abstract class XmlSignatureConfiguration implements Cloneable, CamelConte
public void setSchemaResourceUri(String schemaResourceUri) {
this.schemaResourceUri = schemaResourceUri;
}
+
+ public String getOutputXmlEncoding() {
+ return outputXmlEncoding;
+ }
+
+ /**
+ * The character encoding of the resulting signed XML document. If
+ * <code>null</code> then the encoding of the original XML document is used.
+ *
+ * @param outputXmlEncoding
+ * character encoding
+ */
+ public void setOutputXmlEncoding(String outputXmlEncoding) {
+ this.outputXmlEncoding = outputXmlEncoding;
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerConfiguration.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerConfiguration.java
index e2a25e6..37acb5f 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerConfiguration.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerConfiguration.java
@@ -108,6 +108,8 @@ public class XmlSignerConfiguration extends XmlSignatureConfiguration {
private XmlSignatureProperties properties;
private List<XPathFilterParameterSpec> xpathsToIdAttributes = Collections.emptyList();
+
+ private XPathFilterParameterSpec parentXpath;
/* references that should be resolved when the context changes */
private String keyAccessorName;
@@ -279,13 +281,19 @@ public class XmlSignerConfiguration extends XmlSignatureConfiguration {
/**
* Local name of the parent element to which the XML signature element will
- * be added. Only relevant for enveloped XML signature. Default value is
+ * be added. Only relevant for enveloped XML signature. Alternatively you can
+ * also use {@link #setParentXpath(XPathFilterParameterSpec)}.
+ *
+ * <p> Default value is
* <code>null</code>. The value must be <code>null</code> for enveloping and
* detached XML signature.
* <p>
- * This parameter for enveloped signature and the parameter
- * {@link #setXpathsToIdAttributes(List)} for detached signature must not be
- * set in the same configuration.
+ * This parameter or the parameter {@link #setParentXpath(XPathFilterParameterSpec)}
+ * for enveloped signature and the parameter {@link #setXpathsToIdAttributes(List)}
+ * for detached signature must not be set in the same configuration.
+ * <p>
+ * If the parameters <tt>parentXpath</tt> and <tt>parentLocalName</tt> are specified
+ * in the same configuration then an exception is thrown.
*
* @param parentLocalName
* local name
@@ -455,9 +463,9 @@ public class XmlSignerConfiguration extends XmlSignatureConfiguration {
* You can also set the XPATH list dynamically via the header
* {@link XmlSignatureConstants#HEADER_XPATHS_TO_ID_ATTRIBUTES}.
* <p>
- * The parameter {@link #setParentLocalName(String)} for enveloped signature
- * and this parameter for detached signature must not be set in the same
- * configuration.
+ * The parameter {@link #setParentLocalName(String)} or {@link #setParentXpath(XPathFilterParameterSpec)}
+ * for enveloped signature and this parameter for detached signature must not
+ * be set in the same configuration.
*
* @param xpathsToIdAttributes
*/
@@ -469,4 +477,24 @@ public class XmlSignerConfiguration extends XmlSignatureConfiguration {
}
}
+ public XPathFilterParameterSpec getParentXpath() {
+ return parentXpath;
+ }
+
+ /** Sets the XPath to find the parent node in the enveloped case.
+ * Either you specify the parent node via this method or the local name and namespace of the parent
+ * with the methods {@link #setParentLocalName(String)} and {@link #setParentNamespace(String)}.
+ * <p>
+ * Default value is <code>null</code>. The value must be <code>null</code> for enveloping and
+ * detached XML signature.
+ * <p>
+ * If the parameters <tt>parentXpath</tt> and <tt>parentLocalName</tt> are specified
+ * in the same configuration then an exception is thrown.
+ *
+ * @param parentXpath xpath to the parent node, if the xpath returns several values then the first Element node is used
+ */
+ public void setParentXpath(XPathFilterParameterSpec parentXpath) {
+ this.parentXpath = parentXpath;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java
index 4607aff..6d774e2 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlSignerProcessor.java
@@ -217,9 +217,10 @@ public class XmlSignerProcessor extends XmlSignatureProcessor {
Document outputDoc = sign(out);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- XmlSignatureHelper.transformNonTextNodeToOutputStream(outputDoc, outStream, omitXmlDeclaration(out));
+ XmlSignatureHelper.transformNonTextNodeToOutputStream(outputDoc, outStream, omitXmlDeclaration(out), getConfiguration().getOutputXmlEncoding());
byte[] data = outStream.toByteArray();
out.setBody(data);
+ setOutputEncodingToMessageHeader(out);
clearMessageHeaders(out);
LOG.debug("XML signature generation finished");
} catch (Exception e) {
@@ -270,7 +271,7 @@ public class XmlSignerProcessor extends XmlSignatureProcessor {
signatureId = null;
}
- // parent only relevant for enveloping or detached signature
+ // parent only relevant for enveloped or detached signature
Node parent = getParentOfSignature(out, node, contentReferenceUri, signatureType);
XmlSignatureProperties.Input input = new InputBuilder().contentDigestAlgorithm(getDigestAlgorithmUri()).keyInfo(keyInfo)
@@ -314,16 +315,31 @@ public class XmlSignerProcessor extends XmlSignatureProcessor {
}
private SignatureType determineSignatureType(Message message) throws XmlSignatureException {
+ if (getConfiguration().getParentLocalName() != null && getConfiguration().getParentXpath() != null) {
+ throw new XmlSignatureException(
+ "The configuration of the XML signer component is wrong. The parent local name "
+ + getConfiguration().getParentLocalName()
+ + " and the parent XPath " + getConfiguration().getParentXpath().getXPath() + " are specified. You must not specify both parameters.");
+
+ }
- boolean isEnveloped = getConfiguration().getParentLocalName() != null;
+ boolean isEnveloped = getConfiguration().getParentLocalName() != null || getConfiguration().getParentXpath() != null;
boolean isDetached = getXpathToIdAttributes(message).size() > 0;
if (isEnveloped && isDetached) {
- throw new XmlSignatureException(
+ if (getConfiguration().getParentLocalName() != null) {
+ throw new XmlSignatureException(
"The configuration of the XML signer component is wrong. The parent local name "
+ getConfiguration().getParentLocalName()
+ " for an enveloped signature and the XPATHs to ID attributes for a detached signature are specified. You must not specify both parameters.");
+ } else {
+ throw new XmlSignatureException(
+ "The configuration of the XML signer component is wrong. The parent XPath "
+ + getConfiguration().getParentXpath().getXPath()
+ + " for an enveloped signature and the XPATHs to ID attributes for a detached signature are specified. You must not specify both parameters.");
+
+ }
}
SignatureType result;
@@ -458,19 +474,41 @@ public class XmlSignerProcessor extends XmlSignatureProcessor {
}
}
-
+
protected Element getParentForEnvelopedCase(Document doc, Message inMessage) throws Exception { //NOPMD
-
- NodeList parents = doc.getElementsByTagNameNS(getConfiguration().getParentNamespace(), getConfiguration().getParentLocalName());
-
- if (parents == null || parents.getLength() == 0) {
- throw new XmlSignatureFormatException(
- String.format(
- "Incoming message has wrong format: The parent element with the local name %s and the namespace %s was not found in the message to build an enveloped XML signature.",
- getConfiguration().getParentLocalName(), getConfiguration().getParentNamespace()));
+ if (getConfiguration().getParentXpath() != null) {
+ XPathFilterParameterSpec xp = getConfiguration().getParentXpath();
+ XPathExpression exp;
+ try {
+ exp = XmlSignatureHelper.getXPathExpression(xp);
+ } catch (XPathExpressionException e) {
+ throw new XmlSignatureException("The parent XPath " + getConfiguration().getParentXpath().getXPath() + " is wrongly configured: The XPath " + xp.getXPath() + " is invalid.", e);
+ }
+ NodeList list = (NodeList) exp.evaluate(doc.getDocumentElement(), XPathConstants.NODESET);
+ if (list == null || list.getLength() == 0) {
+ throw new XmlSignatureException("The parent XPath " + xp.getXPath() + " returned no result. Check the configuration of the XML signer component.");
+ }
+ int length = list.getLength();
+ for (int i = 0; i < length; i++) {
+ Node node = list.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ // return the first element
+ return (Element)node;
+ }
+ }
+ throw new XmlSignatureException("The parent XPath " + xp.getXPath() + " returned no element. Check the configuration of the XML signer component.");
+ } else {
+ // parent local name is not null!
+ NodeList parents = doc.getElementsByTagNameNS(getConfiguration().getParentNamespace(), getConfiguration().getParentLocalName());
+ if (parents == null || parents.getLength() == 0) {
+ throw new XmlSignatureFormatException(
+ String.format(
+ "Incoming message has wrong format: The parent element with the local name %s and the namespace %s was not found in the message to build an enveloped XML signature.",
+ getConfiguration().getParentLocalName(), getConfiguration().getParentNamespace()));
+ }
+ // return the first element
+ return (Element) parents.item(0);
}
- // return the first element
- return (Element) parents.item(0);
}
private Element getParentForDetachedCase(Document doc, Message inMessage, String referenceUri) throws XmlSignatureException {
@@ -800,6 +838,13 @@ public class XmlSignerProcessor extends XmlSignatureProcessor {
}
return keyInfo.getId();
}
+
+ protected void setOutputEncodingToMessageHeader(Message message) {
+ if (getConfiguration().getOutputXmlEncoding() != null) {
+ message.setHeader(Exchange.CHARSET_NAME, getConfiguration().getOutputXmlEncoding());
+ }
+ }
+
private static class InputBuilder {
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
index 37e2cc7..b606ec1 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
@@ -204,9 +204,15 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
return getConfiguration().getOutputNodeSearchType();
}
+ @Override
public Boolean getRemoveSignatureElements() {
return getConfiguration().getRemoveSignatureElements();
}
+
+ @Override
+ public String getOutputXmlEncoding() {
+ return getConfiguration().getOutputXmlEncoding();
+ }
};
getConfiguration().getXmlSignature2Message().mapToMessage(refsAndObjects, out);
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/ECDSASignatureTest.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/ECDSASignatureTest.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/ECDSASignatureTest.java
index 80da3a2..7e35d99 100644
--- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/ECDSASignatureTest.java
+++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/ECDSASignatureTest.java
@@ -46,7 +46,7 @@ import org.junit.Test;
*/
public class ECDSASignatureTest extends CamelTestSupport {
- private static String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ private static String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
private boolean canTest = true;
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
index 3f7f089..f3f0957 100644
--- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
+++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
@@ -69,4 +69,31 @@ public class SpringXmlSignatureTest extends XmlSignatureTest {
+ "schemaResourceUri=org/apache/camel/component/xmlsecurity/Test.xsd&signatureId=&clearHeaders=false");
return endpoint;
}
+
+ @Override
+ XmlSignerEndpoint getSignatureEncpointForSignException() {
+ XmlSignerEndpoint endpoint = (XmlSignerEndpoint)context().getEndpoint(//
+ "xmlsecurity:sign://signexceptioninvalidkey?keyAccessor=#accessorRsa");
+ return endpoint;
+ }
+
+ @Override
+ String getVerifierEndpointURIEnveloped() {
+ return "xmlsecurity:verify://enveloped?keySelector=#selectorRsa";
+ }
+
+ @Override
+ String getSignerEndpointURIEnveloped() {
+ return "xmlsecurity:sign://enveloped?keyAccessor=#accessorRsa&parentLocalName=root&parentNamespace=http://test/test";
+ }
+
+ @Override
+ String getVerifierEncpointURIEnveloping() {
+ return "xmlsecurity:verify://enveloping?keySelector=#selectorRsa";
+ }
+
+ @Override
+ String getSignerEndpointURIEnveloping() {
+ return "xmlsecurity:sign://enveloping?keyAccessor=#accessorRsa";
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
index 0965d3c..a363e6a 100644
--- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
+++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
import java.security.Key;
import java.security.KeyException;
import java.security.KeyPair;
@@ -66,7 +67,6 @@ import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
-
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
@@ -101,10 +101,9 @@ import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Before;
import org.junit.Test;
-
public class XmlSignatureTest extends CamelTestSupport {
- private static String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ private static String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
private KeyPair keyPair;
@@ -133,6 +132,8 @@ public class XmlSignatureTest extends CamelTestSupport {
.singletonList(XmlSignatureHelper.getXpathFilter("/ns:root/a/@ID", namespaceMap));
registry.bind("xpathsToIdAttributes", xpaths);
+ registry.bind("parentXpathBean", getParentXPathBean());
+
return registry;
}
@@ -142,8 +143,8 @@ public class XmlSignatureTest extends CamelTestSupport {
public void configure() throws Exception {
// START SNIPPET: enveloping XML signature
onException(XmlSignatureException.class).handled(true).to("mock:exception");
- from("direct:enveloping").to("xmlsecurity:sign://enveloping?keyAccessor=#accessor&schemaResourceUri=")
- .to("xmlsecurity:verify://enveloping?keySelector=#selector").to("mock:result");
+ from("direct:enveloping").to(getSignerEndpointURIEnveloping()).to("mock:signed").to(getVerifierEncpointURIEnveloping())
+ .to("mock:result");
// END SNIPPET: enveloping XML signature
}
}, new RouteBuilder() {
@@ -160,9 +161,8 @@ public class XmlSignatureTest extends CamelTestSupport {
public void configure() throws Exception {
// START SNIPPET: enveloped XML signature
onException(XmlSignatureException.class).handled(true).to("mock:exception");
- from("direct:enveloped")
- .to("xmlsecurity:sign://enveloped?keyAccessor=#accessor&parentLocalName=root&parentNamespace=http://test/test")
- .to("xmlsecurity:verify://enveloped?keySelector=#selector").to("mock:result");
+ from("direct:enveloped").to(getSignerEndpointURIEnveloped()).to("mock:signed").to(getVerifierEndpointURIEnveloped())
+ .to("mock:result");
// END SNIPPET: enveloped XML signature
}
}, new RouteBuilder() {
@@ -208,12 +208,14 @@ public class XmlSignatureTest extends CamelTestSupport {
}
}, new RouteBuilder() {
public void configure() throws Exception {
- // START SNIPPET: transforms XSLT,XPath - secure Validation disabled
+ // START SNIPPET: transforms XSLT,XPath - secure Validation
+ // disabled
from("direct:transformsXsltXPathSecureValDisabled")
.to("xmlsecurity:sign://transformsXsltXPathSecureValDisabled?keyAccessor=#accessor&transformMethods=#transformsXsltXPath",
"xmlsecurity:verify://transformsXsltXPathSecureValDisabled?keySelector=#selector&secureValidation=false")
.to("mock:result");
- // END SNIPPET: transforms XSLT,XPath - secure Validation disabled
+ // END SNIPPET: transforms XSLT,XPath - secure Validation
+ // disabled
}
}, new RouteBuilder() {
public void configure() throws Exception {
@@ -314,38 +316,34 @@ public class XmlSignatureTest extends CamelTestSupport {
}
}, new RouteBuilder() {
public void configure() throws Exception {
- // START SNIPPET: NoSuchAlgorithmException
onException(XmlSignatureException.class).handled(true).to("mock:exception");
from("direct:noSuchAlgorithmException")
.to("xmlsecurity:sign://noSuchAlgorithmException?keyAccessor=#accessor&signatureAlgorithm=wrongalgorithm&digestAlgorithm=http://www.w3.org/2001/04/xmlenc#sha512")
.to("mock:result");
- // END SNIPPET: NoSuchAlgorithmException
}
}, new RouteBuilder() {
public void configure() throws Exception {
- // START SNIPPET: verifier exceptions
onException(XmlSignatureException.class).handled(false).to("mock:exception");
from("direct:verifyexceptions").to("xmlsecurity:verify://verifyexceptions?keySelector=#selector").to("mock:result");
- // END SNIPPET: verifier exceptions
}
}, new RouteBuilder() {
public void configure() throws Exception {
- // START SNIPPET: verifier InvalidKeyException
onException(XmlSignatureException.class).handled(false).to("mock:exception");
from("direct:verifyInvalidKeyException").to("xmlsecurity:verify://verifyInvalidKeyException?keySelector=#selector").to(
"mock:result");
- // END SNIPPET: verifier exceptions
}
}, new RouteBuilder() {
public void configure() throws Exception {
- // START SNIPPET: verifier InvalidHashException
onException(XmlSignatureException.class).handled(false).to("mock:exception");
from("direct:invalidhash").to(
"xmlsecurity:verify://invalidhash?keySelector=#selectorKeyValue&baseUri=#baseUri&secureValidation=false").to(
"mock:result");
- // END SNIPPET: verifier InvalidHashException
}
- }, new RouteBuilder() {
+ }, createDetachedRoute(), createRouteForEnvelopedWithParentXpath() };
+ }
+
+ RouteBuilder createDetachedRoute() {
+ return new RouteBuilder() {
public void configure() throws Exception {
// START SNIPPET: detached XML signature
onException(Exception.class).handled(false).to("mock:exception");
@@ -357,8 +355,18 @@ public class XmlSignatureTest extends CamelTestSupport {
.to("mock:verified");
// END SNIPPET: detached XML signature
}
- }
+ };
+ }
+ private RouteBuilder createRouteForEnvelopedWithParentXpath() {
+ return new RouteBuilder() {
+ public void configure() throws Exception {
+ // START SNIPPET: enveloped XML signature with parent XPath
+ onException(XmlSignatureException.class).handled(false).to("mock:exception");
+ from("direct:envelopedParentXpath").to("xmlsecurity:sign://enveloped?keyAccessor=#accessor&parentXpath=#parentXpathBean")
+ .to("mock:signed").to(getVerifierEndpointURIEnveloped()).to("mock:result");
+ // END SNIPPET: enveloped XML signature with parent XPath
+ }
};
}
@@ -474,7 +482,7 @@ public class XmlSignatureTest extends CamelTestSupport {
@Test
public void testSetTransformMethodXpath2InRouteDefinition() throws Exception {
// example from http://www.w3.org/TR/2002/REC-xmldsig-filter2-20021108/
- String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<Document xmlns=\"http://test/test\"> "
+ "<ToBeSigned> "
+ " <!-- comment --> "
@@ -791,7 +799,8 @@ public class XmlSignatureTest extends CamelTestSupport {
@Test
public void testSignatureIdAtributeNull() throws Exception {
- // the signature Id parameter must be empty, this is set in the URI already
+ // the signature Id parameter must be empty, this is set in the URI
+ // already
Element sigEle = testDetachedSignatureInternal();
Attr attr = sigEle.getAttributeNode("Id");
assertNull("Signature element contains Id attribute", attr);
@@ -821,7 +830,7 @@ public class XmlSignatureTest extends CamelTestSupport {
private Element testDetachedSignatureInternal() throws InterruptedException, XPathExpressionException, SAXException, IOException,
ParserConfigurationException {
- String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + //
+ String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>";
MockEndpoint mock = getMockEndpoint("mock:result");
mock.expectedMessageCount(1);
@@ -860,7 +869,7 @@ public class XmlSignatureTest extends CamelTestSupport {
void testDetached2Xpaths(String xpath1exp, String xpath2exp) throws InterruptedException, XPathExpressionException, SAXException,
IOException, ParserConfigurationException {
- String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + //
+ String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<ns:root xmlns:ns=\"http://test\"><test ID=\"myID\"><b>bValue</b><ts:B xmlns:ts=\"http://testB\"><C ID=\"cID\"><D>dvalue</D></C></ts:B></test></ns:root>";
MockEndpoint mock = getMockEndpoint("mock:result");
mock.expectedMessageCount(1);
@@ -1007,6 +1016,164 @@ public class XmlSignatureTest extends CamelTestSupport {
+ " has no parent element. The element must have a parent element in the configured detached case.", null);
}
+ @Test
+ public void testOutputXmlEncodingEnveloping() throws Exception {
+
+ String inputEncoding = "UTF-8";
+ String signerEncoding = "UTF-16LE";
+ String outputEncoding = "ISO-8859-1"; // latin 1
+
+ String signerEndpointUri = getSignerEndpointURIEnveloping();
+ String verifierEndpointUri = getVerifierEncpointURIEnveloping();
+
+ String directStart = "direct:enveloping";
+
+ checkOutputEncoding(inputEncoding, signerEncoding, outputEncoding, signerEndpointUri, verifierEndpointUri, directStart);
+ }
+
+ String getVerifierEncpointURIEnveloping() {
+ return "xmlsecurity:verify://enveloping?keySelector=#selector";
+ }
+
+ String getSignerEndpointURIEnveloping() {
+ return "xmlsecurity:sign://enveloping?keyAccessor=#accessor&schemaResourceUri=";
+ }
+
+ @Test
+ public void testOutputXmlEncodingEnveloped() throws Exception {
+
+ String inputEncoding = "UTF-8";
+ String signerEncoding = "UTF-16LE";
+ String outputEncoding = "ISO-8859-1"; // latin 1
+
+ String signerEndpointUri = getSignerEndpointURIEnveloped();
+ String verifierEndpointUri = getVerifierEndpointURIEnveloped();
+
+ String directStart = "direct:enveloped";
+
+ checkOutputEncoding(inputEncoding, signerEncoding, outputEncoding, signerEndpointUri, verifierEndpointUri, directStart);
+ }
+
+ String getVerifierEndpointURIEnveloped() {
+ return "xmlsecurity:verify://enveloped?keySelector=#selector";
+ }
+
+ String getSignerEndpointURIEnveloped() {
+ return "xmlsecurity:sign://enveloped?keyAccessor=#accessor&parentLocalName=root&parentNamespace=http://test/test";
+ }
+
+ private byte[] getPayloadForEncoding(String encoding) {
+ String s = "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n"
+ + "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
+ return s.getBytes(Charset.forName(encoding));
+ }
+
+ @Test
+ public void testExceptionParentLocalNameAndXPathSet() throws Exception {
+
+ XmlSignerEndpoint endpoint = getSignatureEncpointForSignException();
+ MockEndpoint mock = setupExceptionMock();
+ try {
+ endpoint.setParentXpath(getNodeSerachXPath());
+ endpoint.setParentLocalName("root");
+ sendBody("direct:signexceptions", payload);
+ assertMockEndpointsSatisfied();
+ checkThrownException(mock, XmlSignatureException.class, "The configuration of the XML signer component is wrong. " + //
+ "The parent local name root and the parent XPath //pre:root are specified. You must not specify both parameters.", null);
+ } finally {
+ endpoint.setParentXpath(null);
+ endpoint.setParentLocalName(null);
+ }
+ }
+
+ @Test
+ public void testExceptionXpathsToIdAttributesNameAndXPathSet() throws Exception {
+
+ XmlSignerEndpoint endpoint = getSignatureEncpointForSignException();
+ MockEndpoint mock = setupExceptionMock();
+ try {
+ endpoint.setParentXpath(getNodeSerachXPath());
+ List<XPathFilterParameterSpec> xpaths = Collections.singletonList(XmlSignatureHelper.getXpathFilter("/ns:root/a/@ID", null));
+ endpoint.setXpathsToIdAttributes(xpaths);
+ sendBody("direct:signexceptions", payload);
+ assertMockEndpointsSatisfied();
+ checkThrownException(
+ mock,
+ XmlSignatureException.class,
+ "The configuration of the XML signer component is wrong. " + //
+ "The parent XPath //pre:root for an enveloped signature and the XPATHs to ID attributes for a detached signature are specified. You must not specify both parameters.",
+ null);
+ } finally {
+ endpoint.setParentXpath(null);
+ endpoint.setXpathsToIdAttributes(null);
+ }
+ }
+
+ @Test
+ public void testExceptionInvalidParentXpath() throws Exception {
+
+ XmlSignerEndpoint endpoint = getSignatureEncpointForSignException();
+ MockEndpoint mock = setupExceptionMock();
+ try {
+ endpoint.setParentXpath(XmlSignatureHelper.getXpathFilter("//pre:root", null)); // invalid xpath: namespace-prefix mapping is missing
+ sendBody("direct:signexceptions", payload);
+ assertMockEndpointsSatisfied();
+ checkThrownException(mock, XmlSignatureException.class,
+ "The parent XPath //pre:root is wrongly configured: The XPath //pre:root is invalid.", null);
+ } finally {
+ endpoint.setParentXpath(null);
+ }
+ }
+
+ @Test
+ public void testExceptionParentXpathWithNoResult() throws Exception {
+
+ XmlSignerEndpoint endpoint = getSignatureEncpointForSignException();
+ MockEndpoint mock = setupExceptionMock();
+ try {
+ endpoint.setParentXpath(XmlSignatureHelper.getXpathFilter("//root", null)); // xpath with no result
+ sendBody("direct:signexceptions", payload);
+ assertMockEndpointsSatisfied();
+ checkThrownException(mock, XmlSignatureException.class,
+ "The parent XPath //root returned no result. Check the configuration of the XML signer component.", null);
+ } finally {
+ endpoint.setParentXpath(null);
+ }
+ }
+
+ XmlSignerEndpoint getSignatureEncpointForSignException() {
+ XmlSignerEndpoint endpoint = (XmlSignerEndpoint) context().getEndpoint("xmlsecurity:sign://signexceptions?keyAccessor=#accessor" + //
+ "&signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512");
+ return endpoint;
+ }
+
+ @Test
+ public void testExceptionParentXpathWithNoElementResult() throws Exception {
+
+ XmlSignerEndpoint endpoint = getSignatureEncpointForSignException();
+ MockEndpoint mock = setupExceptionMock();
+ try {
+ String myPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
+ "<ns:root ID=\"rootId\" xmlns:ns=\"http://test\"></ns:root>";
+ endpoint.setParentXpath(XmlSignatureHelper.getXpathFilter("/pre:root/@ID", Collections.singletonMap("pre", "http://test"))); // xpath with no element result
+ sendBody("direct:signexceptions", myPayload);
+ assertMockEndpointsSatisfied();
+ checkThrownException(mock, XmlSignatureException.class,
+ "The parent XPath /pre:root/@ID returned no element. Check the configuration of the XML signer component.", null);
+ } finally {
+ endpoint.setParentXpath(null);
+ }
+ }
+
+ @Test
+ public void testEnvelopedSignatureWithParentXpath() throws Exception {
+ String myPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<ns:root xmlns:ns=\"http://test\"><a>a1</a><a/><test>Test Message</test></ns:root>";
+ setupMock(myPayload);
+ sendBody("direct:envelopedParentXpath", myPayload);
+ assertMockEndpointsSatisfied();
+ }
+
XmlSignerEndpoint getDetachedSignerEndpoint() {
XmlSignerEndpoint endpoint = (XmlSignerEndpoint) context().getEndpoint(
"xmlsecurity:sign://detached?keyAccessor=#keyAccessorDefault&xpathsToIdAttributes=#xpathsToIdAttributes&"//
@@ -1014,6 +1181,39 @@ public class XmlSignatureTest extends CamelTestSupport {
return endpoint;
}
+ private void checkOutputEncoding(String inputEncoding, String signerEncoding, String outputEncoding, String signerEndpointUri,
+ String verifierEndpointUri, String directStart) throws InterruptedException, UnsupportedEncodingException {
+ byte[] inputPayload = getPayloadForEncoding(inputEncoding);
+ byte[] expectedPayload = getPayloadForEncoding(outputEncoding);
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedBodiesReceived(expectedPayload);
+
+ MockEndpoint mockSigned = getMockEndpoint("mock:signed");
+ mock.expectedMessageCount(1);
+
+ XmlSignerEndpoint endpointSigner = (XmlSignerEndpoint) context().getEndpoint(signerEndpointUri);
+
+ XmlVerifierEndpoint endpoinVerifier = (XmlVerifierEndpoint) context().getEndpoint(verifierEndpointUri);
+ try {
+ endpointSigner.setOutputXmlEncoding(signerEncoding);
+ endpoinVerifier.setOutputXmlEncoding(outputEncoding);
+ sendBody(directStart, inputPayload);
+ assertMockEndpointsSatisfied();
+ Message signedMessage = mockSigned.getExchanges().get(0).getIn();
+ byte[] signedBytes = signedMessage.getBody(byte[].class);
+ String signedPayload = new String(signedBytes, signerEncoding);
+ assertTrue(signedPayload.contains(signerEncoding));
+ String charsetHeaderSigner = signedMessage.getHeader(Exchange.CHARSET_NAME, String.class);
+ assertEquals(signerEncoding, charsetHeaderSigner);
+ String charsetHeaderVerifier = mock.getExchanges().get(0).getIn().getHeader(Exchange.CHARSET_NAME, String.class);
+ assertEquals(outputEncoding, charsetHeaderVerifier);
+ } finally {
+ endpointSigner.setOutputXmlEncoding(null);
+ endpoinVerifier.setOutputXmlEncoding(null);
+ }
+ }
+
private void checkBodyContains(MockEndpoint mock, String expectedPartContent) {
Message message = getMessage(mock);
String body = message.getBody(String.class);
@@ -1350,4 +1550,9 @@ public class XmlSignatureTest extends CamelTestSupport {
return SameDocumentUriDereferencer.getInstance();
}
+ public static XPathFilterParameterSpec getParentXPathBean() {
+ Map<String, String> prefix2Namespace = Collections.singletonMap("ns", "http://test");
+ return XmlSignatureHelper.getXpathFilter("/ns:root/a[last()]", prefix2Namespace);
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/b8ca2bac/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTests.xml
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTests.xml b/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTests.xml
index 96ccd0c..53443a0 100644
--- a/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTests.xml
+++ b/components/camel-xmlsecurity/src/test/resources/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTests.xml
@@ -30,6 +30,7 @@
<route>
<from uri="direct:enveloping" />
<to uri="xmlsecurity:sign://enveloping?keyAccessor=#accessorRsa" />
+ <to uri="mock:signed" />
<to
uri="xmlsecurity:verify://enveloping?keySelector=#selectorRsa" />
<to uri="mock:result" />
@@ -52,6 +53,7 @@
<from uri="direct:enveloped" />
<to
uri="xmlsecurity:sign://enveloped?keyAccessor=#accessorRsa&parentLocalName=root&parentNamespace=http://test/test" />
+ <to uri="mock:signed" />
<to
uri="xmlsecurity:verify://enveloped?keySelector=#selectorRsa" />
<to uri="mock:result" />
@@ -270,6 +272,16 @@
</route>
<!-- END SNIPPET: detached -->
+ <!-- START SNIPPET: enveloped XML signature with parent XPath -->
+ <route>
+ <from uri="direct:envelopedParentXpath" />
+ <to
+ uri="xmlsecurity:sign://enveloped?keyAccessor=#accessorRsa&parentXpath=#parentXpathBean" />
+ <to
+ uri="xmlsecurity:verify://enveloped?keySelector=#selectorRsa" />
+ <to uri="mock:result" />
+ </route>
+ <!-- END SNIPPET: enveloped XML signature with parent XPath -->
</camelContext>
@@ -436,4 +448,8 @@
</list>
</constructor-arg>
</bean>
+
+ <bean id="parentXpathBean"
+ class="org.apache.camel.component.xmlsecurity.SpringXmlSignatureTest"
+ factory-method="getParentXPathBean" />
</beans>