You can PROBABLY achieve this by creating a subclass of DataHandler and
overriding the writeTo.... method. Something like:
final DeferredDocumentImpl signedDoc
= new XmlSign().createSignedDocument(new FileInputStream("a_file.xml"));
DataHandler dh = new DataHandler(signedDoc, "text/xml") {
public void writeTo(OutputStream out) {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(signedDoc ), new StreamResult(out));
}
}
That said, that could be made automatic, I think. You don't say where the
WebServiceRequest object comes from. Is that generated from WSDL? I think
if you add xmime:expectedContentTypes="text/xml" to the element that defines
the base64binary data, the code generator would then generate it as a Document
instead of a DataHandler. Thus, you could just set the document in and be
done.
Dan
On Thu November 26 2009 7:39:32 am emilSverige wrote:
> Hi, I want to sign an MTOM attachment only, not the soap message. I am
> aware that the WSS4J-interceptor doesn't sign the attachment, so I'm
> trying to do it in plain java instead.
>
> Please note that the soap message should be unsigned, only the attachment
> should be signed.
>
> So far I have managed to sign an attachment and save it to disk, then read
> it and send with cxf. No problem, but I would like to get rid of the "save
> to disk" part since it seems unnecessary.
>
> Unfortunately though, I don't know how to. I have no idea how a Datahandler
> can handle a DeferredDocumentImpl. Any help is appreciated!
>
> This is the code that signs, saves to disk, reads from disk and prepares
> the request:
>
> /**
> * @param fileInputStream The data to sign
> * @return A signed document
> */
> DeferredDocumentImpl createSignedDocument(FileInputStream fileInputStream){
> // Create a DOM XMLSignatureFactory that will be used to
> generate
the
> // enveloped signature
> XMLSignatureFactory fac =
> XMLSignatureFactory.getInstance("DOM");
>
> // Create a Reference to the enveloped document (in this case
> we are
> // signing the whole document, so a URI of "" signifies that)
> and
> // also specify the SHA1 digest algorithm and the ENVELOPED
Transform.
> Reference ref = fac.newReference("", fac.newDigestMethod(
> DigestMethod.SHA1, null),
> Collections.singletonList(fac
> .newTransform(Transform.ENVELOPED,
> (TransformParameterSpec) null)), null, null);
>
> // Create the SignedInfo
> SignedInfo si = fac
> .newSignedInfo(fac.newCanonicalizationMethod(
> CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
> (C14NMethodParameterSpec) null), fac
> .newSignatureMethod(SignatureMethod.RSA_SHA1,
> null),
> Collections.singletonList(ref));
>
> KeyStore keystore = KeyStore.getInstance("JKS");
> keystore.load(new FileInputStream("myKeystore.jks"),
> "aPassword".toCharArray());
>
> PrivateKey privateKey = (PrivateKey)keystore.getKey( "MyAlias",
> "aPassword".toCharArray());
>
> KeyStore.PasswordProtection password = new
> KeyStore.PasswordProtection("aPassword".toCharArray());
> KeyStore.PrivateKeyEntry thePrivKeyEntry =
(KeyStore.PrivateKeyEntry)
> keystore.getEntry("myAlias", password);
> X509Certificate cert = (X509Certificate)
> thePrivKeyEntry.getCertificate();
>
> // Create the KeyInfo containing the X509Data.
> KeyInfoFactory kif = fac.getKeyInfoFactory();
> List x509Content = new ArrayList();
> x509Content.add(cert.getSubjectX500Principal().getName());
> x509Content.add(cert);
> X509Data xd = kif.newX509Data(x509Content);
> KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
>
>
> // Instantiate the document to be signed
> DocumentBuilderFactory dbf =
> DocumentBuilderFactory.newInstance();
> dbf.setNamespaceAware(true);
> Document doc = dbf.newDocumentBuilder().parse(fileInputStream);
>
> // Create a DOMSignContext and specify the DSA PrivateKey and
> // location of the resulting XMLSignature's parent element
> DOMSignContext dsc = new DOMSignContext(privateKey, doc
> .getDocumentElement());
>
> // Create the XMLSignature (but don't sign it yet)
> XMLSignature signature = fac.newXMLSignature(si, ki);
>
> // Marshal, generate (and sign) the enveloped signature
> signature.sign(dsc);
>
> return doc;
> }
>
> public void sendAnAttachmentWithSignature(){
> // Sign the dokument
> DeferredDocumentImpl signedDoc = new XmlSign().createSignedDocument( new
> FileInputStream("a_file.xml") );
>
> // Save it to disk
> OutputStream os = new FileOutputStream( "a_signed_file.xml" );
> TransformerFactory tf =
> TransformerFactory.newInstance();
> Transformer trans = tf.newTransformer();
> trans.transform(new DOMSource(signedDoc ), new
StreamResult(os));
>
> // Create a DataHandler to attach to the web service klient
> DataHandler dh = new DataHandler(
> new FileDataSource(
> new File("a_signed_file.xml" )) );
>
> // Add the datahandler to the request object
> WebServiceRequest req = new WebServiceRequest();
> req.setData( dh );
>
> // Then send the request...
>
> }
>
--
Daniel Kulp
[email protected]
http://www.dankulp.com/blog