Add Signature in a SOAP request in Apache JMeter - soap
I need to add signature using X509 certificate in SOAP request in Apache JMeter.
I already have .p12 with me.
Please help how can I achieve it in Apache JMeter.
I know how to do it in SOAPUI but not finding any way in JMeter.
don't know wheter you need this answer still but I ran into the same problem and got it fixed after a couple of days of work and I suppose others might find this usefull as well...
I based my answer upon the answer by Dmitri T; the blog post on blazemeter, this bugreport + some custom hacking.
Let's assume you need to sign this request:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ser="http://custom.namespace.com/service-v1.0-rc2">
<soap:Header>
<wsa:MessageID xmlns:wsa="http://www.w3.org/2004/12/addressing">a2749a0f-555-9135-367ed901d244</wsa:MessageID>
</soap:Header>
<soap:Body>
<ser:request>
<ser:person>
<ser:id>11552</ser:id>
<ser:number>81067776992</ser:number>
</ser:person>
</ser:request>
</soap:Body>
</soap:Envelope>
You've followed the guide on blazemeter until the part with the custom java code to sign the request.
In stead of using that code do the following:
Copy paste the following code into JMeter(3.0):
import com.example.wss.SOAPSecurity;
import org.apache.jmeter.services.FileServer;
// get SOAP message from parent sampler body
String soapData = sampler.getArguments().getArgument(0).getValue();
String baseDir = FileServer.getFileServer().getBaseDir();
String pathToKeystore = baseDir + File.separator + "keystore_files" + File.separator + "your.jks";
String keystorePassword = "yourPassword";
int timeToLive = 5000;
String signingAlias = "yourAlias";
String encryptAlias = "yourEncryptingAlias";
String secureSoap = "";
try {
secureSoap = SOAPSecurity.secureSoapMessageFromString(soapData, pathToKeystore, keystorePassword, null, null, timeToLive, signingAlias, yourEncryptingAlias);
}
catch (Exception ex){
log.warn("Error in script", ex);
throw ex;
}
// replace parent sampler body with secured SOAP message
sampler.getArguments().getArgument(0).setValue(secureSoap);
vars.put("SoapDataRaw", secureSoap);
Use groovy as interpreter.
This is the java class file adapted for my use case:
package com.example.wss;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.components.crypto.Merlin;
import org.apache.ws.security.message.WSSecEncrypt;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecTimestamp;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.net.ssl.*;
import javax.xml.transform.dom.DOMSource;
import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class SOAPSecurity {
private KeyStore keystore;
private KeyManagerFactory keyManagerFactory;
private String keystorePassword;
private TrustManagerFactory trustManagerFactory;
private KeyStore truststore;
private String truststorePassword;
private Crypto crypto;
public SOAPSecurity(String pathToKeystore, String keystorePassword, String pathToTruststore, String truststorePassword) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException, WSSecurityException {
keystore = KeyStore.getInstance("JKS");
InputStream fileReader = new FileInputStream(new File(pathToKeystore));
keystore.load(fileReader, keystorePassword.toCharArray());
this.keystorePassword = keystorePassword;
keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keystore, keystorePassword.toCharArray());
Properties properties = new Properties();
properties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
crypto = CryptoFactory.getInstance(properties);
((Merlin) crypto).setKeyStore(keystore);
truststore = KeyStore.getInstance("JKS");
fileReader = new FileInputStream(new File(pathToTruststore));
truststore.load(fileReader, truststorePassword.toCharArray());
this.truststorePassword = truststorePassword;
trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(truststore);
}
//EDITOR: added constructor without truststore
public SOAPSecurity(String pathToKeystore, String keystorePassword) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException, WSSecurityException {
keystore = KeyStore.getInstance("JKS");
InputStream fileReader = new FileInputStream(new File(pathToKeystore));
keystore.load(fileReader, keystorePassword.toCharArray());
this.keystorePassword = keystorePassword;
keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keystore, keystorePassword.toCharArray());
Properties properties = new Properties();
properties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
crypto = CryptoFactory.getInstance(properties);
((Merlin) crypto).setKeyStore(keystore);
}
public static String secureSoapMessageFromFile(String messagePath, String pathToKeystore, String keystorePassword,
String pathToTruststore, String trustStorePassword, int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {
SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword, pathToTruststore, trustStorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromFile(messagePath);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}
public static String secureSoapMessageFromString(String messageString, String pathToKeystore, String keystorePassword,
String pathToTruststore, String trustStorePassword, int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {
SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromString(messageString);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}
//EDITOR: ...and static signing methods as well
public static String secureSoapMessageFromString(String messageString, String pathToKeystore, String keystorePassword,
int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {
SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromString(messageString);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}
public static String secureSoapMessageFromFile(String messagePath, String pathToKeystore, String keystorePassword,
int timeToLive,
String signingAlias, String encryptAlias) throws
SAXException, ParserConfigurationException, SOAPException, IOException, WSSecurityException,
TransformerException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {
SOAPSecurity soapSecurity = new SOAPSecurity(pathToKeystore, keystorePassword);
SOAPMessage soapMessage = SOAPSecurity.createSOAPRequestFromFile(messagePath);
return soapSecurity.applyWSSecurity(soapMessage, timeToLive, signingAlias, encryptAlias);
}
public interface SOAPDocWriter {
Document writeDocument(String s, DocumentBuilder documentBuilder) throws IOException, SAXException;
}
public static SOAPMessage createSOAPRequestFromFile(String messagePath) throws SOAPException, IOException, ParserConfigurationException, SAXException {
SOAPDocWriter pathWriter = (s, d) -> {
File messageFile = new File(s);
return d.parse(new InputSource(new FileInputStream(messageFile)));
};
return createSOAPRequestLambda(messagePath, pathWriter);
}
public static SOAPMessage createSOAPRequestFromString(String messageString) throws SOAPException, IOException, ParserConfigurationException, SAXException {
SOAPDocWriter stringWriter = (s, d) -> d.parse(new InputSource(new StringReader(s)));
return createSOAPRequestLambda(messageString, stringWriter);
}
private static SOAPMessage createSOAPRequestLambda(String s, SOAPDocWriter w) throws SOAPException, IOException, ParserConfigurationException, SAXException
{
//MessageFactory messageFactory = MessageFactory.newInstance();
//we use the SOAP 1.2 specification
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPBody soapBody = soapEnvelope.getBody();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = w.writeDocument(s, documentBuilder);
soapBody.addDocument(document);
soapMessage.saveChanges();
return soapMessage;
}
public static Document toDocument(SOAPMessage soapMsg) throws TransformerConfigurationException, TransformerException, SOAPException, IOException {
Source src = soapMsg.getSOAPPart().getContent();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMResult result = new DOMResult();
transformer.transform(src, result);
return (Document) result.getNode();
}
/**
* Secures a soap message according to the given security actions
*
* #param soapMessage the soap message to be secured
* #param timestampTimeToLive optional: the time to live for the timestamp
* #param signatureKeyAlias optional: the alias for the signature key in the keystore
* #param encryptionKeyAlias optional: the alias for the encryption key in the keystore
* #throws WSSecurityException
* #throws IOException
* #throws SOAPException
* #throws TransformerException
*/
public String applyWSSecurity(SOAPMessage soapMessage,
int timestampTimeToLive,
String signatureKeyAlias,
String encryptionKeyAlias) throws WSSecurityException, IOException, SOAPException, TransformerException {
Document soapMessageDocument = toDocument(soapMessage);
// add security header
WSSecHeader securityHeader = new WSSecHeader();
securityHeader.setMustUnderstand(false);
//we keep the security header element because we need it afterwards
Element secHead = securityHeader.insertSecurityHeader(soapMessageDocument);
/*
for a reason not yet clear to me this method of signing creates a soap request inside a soap request
I don't know why but I know how to work around it:
*/
//append the security header to the soap:Header parent
soapMessageDocument.getElementsByTagName("soap:Header").item(0).appendChild(secHead);
//move the soap:Envelope inner soap message to the root of the document and omit the env:Envelope tree
soapMessageDocument.replaceChild(soapMessageDocument.getElementsByTagName("soap:Envelope").item(0),
soapMessageDocument.getElementsByTagName("env:Envelope").item(0));
//for debugging purposes -> this output shows up in the console output of JMeter.bat
//System.out.println("insert:"+soapMessageDocument.getFirstChild().getNodeName()+",soap:"+soapMessageDocument.getElementsByTagName("soap:Envelope").item(0).getNodeName());
WSSecTimestamp timestamp = null;
// timestamp document
timestamp = new WSSecTimestamp();
timestamp.setTimeToLive(timestampTimeToLive);
timestamp.build(soapMessageDocument, securityHeader);
// sign document
/*
EDITOR: originals are commented out and replaced by own values
values should be adapted from SOAPUI and searched for at:
https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/dom/WSConstants.html
*/
WSSecSignature signatureBuilder = new WSSecSignature();
signatureBuilder.setUserInfo(signatureKeyAlias, keystorePassword);
signatureBuilder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
//signatureBuilder.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
signatureBuilder.setSignatureAlgorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha1");
signatureBuilder.setSigCanonicalization(WSConstants.C14N_EXCL_OMIT_COMMENTS);
/*
also setDigestAlgo can be set
https://ws.apache.org/wss4j/apidocs/org/apache/wss4j/dom/message/WSSecSignature.html#setDigestAlgo-java.lang.String-
but I used the default so I didn't bother
*/
//also custom
signatureBuilder.setUseSingleCertificate(true);
List<WSEncryptionPart> signatureParts = new ArrayList<WSEncryptionPart>();
//WSEncryptionPart timestampPart = new WSEncryptionPart(timestamp.getId());
WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd","Content");
signatureParts.add(timestampPart);
//WSEncryptionPart bodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, "Element");
WSEncryptionPart bodyPart = new WSEncryptionPart("Body","http://www.w3.org/2003/05/soap-envelope", "Content");
signatureParts.add(bodyPart);
signatureBuilder.setParts(signatureParts);
signatureBuilder.build(soapMessageDocument, crypto, securityHeader);
// encrypt document
/*
we didn't encrypt so no need for this code
(encryption code untested (by me))
WSSecEncrypt encrypt = new WSSecEncrypt();
encrypt.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
encrypt.setSymmetricEncAlgorithm(WSConstants.AES_128_GCM);
encrypt.setKeyEncAlgo(WSConstants.KEYTRANSPORT_RSAOEP);
encrypt.setUserInfo(encryptionKeyAlias, keystorePassword);
List<WSEncryptionPart> encryptionParts = new ArrayList<WSEncryptionPart>();
WSEncryptionPart encryptionSignaturePart = new WSEncryptionPart("Signature", WSConstants.SIG_NS, "Element");
WSEncryptionPart encryptionBodyPart = new WSEncryptionPart("Body", WSConstants.URI_SOAP11_ENV, "Content");
encryptionParts.add(encryptionBodyPart);
encryptionParts.add(encryptionSignaturePart);
encrypt.setParts(encryptionParts);
encrypt.build(soapMessageDocument, crypto, securityHeader);
*/
DOMSource domSource = new DOMSource(soapMessageDocument);
soapMessage.getSOAPPart().setContent(domSource);
soapMessage.saveChanges();
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapMessage.writeTo(out);
String strMsg = new String(out.toByteArray());
return strMsg;
}
}
Put the code in a com\example\wss\SOAPSecurity.java file
Put wss4j-1.6.18.jar in the same dir.
http://archive.apache.org/dist/ws/wss4j/1.6.18/
I compiled/build/deployed it with this .sh script (you can use cygwin for that):
/cygdrive/c/Program\ Files\ \(x86\)/Java/jdk1.8.0_73/bin/javac.exe -cp wss4j-1.6.18.jar com/example/wss/SOAPSecurity.java
cp SOAPSecurity.jar SOAPSecurity.jar.bak$1
zip -r test.zip com/
mv test.zip SOAPSecurity.jar
cp SOAPSecurity.jar /cygdrive/c/Program\ Files\ \(x86\)/apache-jmeter-3.0/lib/
Run JMeter 3.0 with the .bat file
-> the SOAPSecurity.jar should be in the apache-jmeter-3.0/lib/ folder
-> I have also these configuration in JMeter's system.properties file:
-Djavax.net.ssl.keyStore=C:/path/to/client.jks
-Djavax.net.ssl.keyStorePassword=verySecret
-> and added a keystore configuration element to the soap request in JMeter
So, this is about it, feel free to give it a spin and let me know whether it worked for you, if not I might provide some help, if you'd like to debug yourself an excelent way to do so is by adapting/placing System.out.println's in the custom class, it gives very usefull information about what's going on and can be quite a life saver,
Keep having fun!!!
S.
You need to do some scripting in order to encrypt the message via the JSR223 PreProcessor. The idea is to get current sampler body, encrypt it and replace on-the-fly.
Add JSR223 PreProcessor as a child of the request
Use the following code as a reference:
import com.sun.org.apache.xml.internal.security.Init;
import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
import com.sun.org.apache.xml.internal.security.transforms.Transforms;
import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.apache.jmeter.protocol.http.sampler.SoapSampler;
import org.apache.commons.io.FileUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
//write sampler body into "signature.xml" file
String body = sampler.getXmlData();
FileUtils.writeStringToFile(new File("signature.xml"),body);
//X509 properties
String keystoreType = "JKS";
String keystoreFile = "wso2carbon.jks";
String keystorePass = "wso2carbon";
String privateKeyAlias = "wso2carbon";
String privateKeyPass = "wso2carbon";
String certificateAlias = "wso2carbon";
Element element = null;
String BaseURI = signatureFile.toURI().toURL().toString();
//SOAP envelope to be signed
//get the private key used to sign, from the keystore
KeyStore ks = KeyStore.getInstance(keystoreType);
FileInputStream fis = new FileInputStream(keystoreFile);
ks.load(fis, keystorePass.toCharArray());
PrivateKey privateKey =
(PrivateKey) ks.getKey(privateKeyAlias, privateKeyPass.toCharArray());
//create basic structure of signature
javax.xml.parsers.DocumentBuilderFactory dbf =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
String request = sampler.getXmlData();
ByteArrayInputStream in = new ByteArrayInputStream(request.getBytes());
Document doc = dBuilder.parse(in);
in.close();
Init.init();
XMLSignature sig =
new XMLSignature(doc, BaseURI, XMLSignature.ALGO_ID_SIGNATURE_RSA);
element = doc.getDocumentElement();
element.normalize();
element.getElementsByTagName("soapenv:Header").item(0).appendChild(sig.getElement());
{
Transforms transforms = new Transforms(doc);
transforms.addTransform(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
//Sign the content of SOAP Envelope
sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
}
//Signing procedure
{
X509Certificate cert =
(X509Certificate) ks.getCertificate(certificateAlias);
sig.addKeyInfo(cert);
sig.addKeyInfo(cert.getPublicKey());
sig.sign(privateKey);
}
//write signature to file
FileOutputStream f = new FileOutputStream(signatureFile);
XMLUtils.outputDOMc14nWithComments(doc, f);
f.close();
//set sampler's XML data from file
String request = FileUtils.readFileToString(signatureFile);
sampler.setXmlData(request);
You will need to replace keystore and encryption related bits as per your configuration and service definition
See Take the Pain out of Load Testing Secure Web Services for comprehensive explanation
Related
Sendgrid Inbound Parse webhook and Java MimeMessage Compatibility
I am trying to parse raw mime message which sengrid post to a URL by inbound parse web hook settings. Previously i was listening for incoming mails from Mailserver through Imap and from java MimeMessage i was able to convert it to the String and vice versa. Please see below code how i used to convert from MimeMessage to String and vice versa in java. private void convertMimeMessageToStringAndViceVersa(javax.mail.internet.MimeMessage message) { ByteArrayOutputStream bStream = new ByteArrayOutputStream(); message.writeTo(bStream); String rawMimeMessageString = new String(bStream.toByteArray(), StandardCharsets.UTF_8.name()); // Now from the above String to MimeMessage see below code Properties props = new Properties(); Session session = Session.getDefaultInstance(props, null); ByteArrayInputStream bais = new ByteArrayInputStream(rawMimeMessageString.getBytes()); javax.mail.internet.MimeMessage convertedMimeMessage = new MimeMessage(session, bais); } So my question is, i cannot convert the string raw mail message which sendgrid is posting through inbound parse webhook to javax.mail.internet.MimeMessage type. Is there anyway.
Probably SendGrid Raw MimeMessage is broken, however you can try to use non-raw payload and convert this payload to whatever you want. According to this article: https://varunsastrydevulapalli.medium.com/the-sendgrid-inbound-webhook-with-spring-dc7b5bae4e0c, we can receive the Inbound Message using this spring controller: #Controller #RequestMapping(value = "/messaging") public class InboundMessageController { #Bean(name = "multipartResolver") public CommonsMultipartResolver commonsMultipartResolver() { CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(); commonsMultipartResolver.setDefaultEncoding("UTF-8"); commonsMultipartResolver.setMaxUploadSize(5000); return commonsMultipartResolver; } #RequestMapping(value = "/inbound", method = {RequestMethod.POST, RequestMethod.HEAD}, consumes = MediaType.MULTIPART_FORM_DATA) public #ResponseBody void processInboundSendGridEmails(HttpServletRequest request, HttpServletResponse response, #RequestParam(required = false) MultipartFile file, SendGridInbound sendGridInbound) { System.out.println(sendGridInbound); convertToMimeMessage(sendGridInbound); } } public class SendGridInbound { String headers; String dkim; String to; String html; String from; String text; String sender_ip; String spam_report; String envelope; String attachments; String subject; String spam_score; String attchmentInfo; String charsets; String spf; //getter setters toString } Hope it could help.
The previous solution hasn't worked to me. But the following solution worked fine. This code snippet reads the request through the class MimeMessage, to learn how to deal with that you can read this topic. Here goes the solution: package package_; import org.apache.log4j.Logger; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.MimeMessage; import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; #RestController #RequestMapping("/listener") public class SendGridListener { protected final Logger logger = Logger.getLogger(this.getClass()); #RequestMapping( method = {RequestMethod.POST}, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE} ) public #ResponseBody void listen(HttpServletRequest request) throws MessagingException, IOException { String email = request.getParameter("email"); Session s = Session.getInstance(new Properties()); InputStream is = new ByteArrayInputStream(email.getBytes()); MimeMessage message = new MimeMessage(s, is); logger.info(message); } }
How to send TestNG emailable report to email from maven?
I am using the below snippet for sending emailable-report.html of testng through mail. public class SampleSendMail { public void sendmailfun() { String username = "mailid"; String password = "password"; Properties props = new Properties(); props.put("mail.smtp.auth", true); props.put("mail.smtp.starttls.enable", true); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.port", "587"); Session session = Session.getInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress("sendingmailid")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("receivingmailid")); message.setSubject("Testing Subject"); message.setText("PFA"); MimeBodyPart messageBodyPart = new MimeBodyPart(); Multipart multipart = new MimeMultipart(); messageBodyPart = new MimeBodyPart(); String file = "/Users/Documents/workspace/sampleproject/test-output/emailable-report.html"; String fileName = "emailable-report.html"; DataSource source = new FileDataSource(file); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(fileName); multipart.addBodyPart(messageBodyPart); message.setContent(multipart); System.out.println("Sending"); Transport.send(message); System.out.println("Done"); } catch (MessagingException e) { e.printStackTrace(); } } } In #AfterSuite ,i'm callig this function. public void appstop() throws IOException { sendingemail.sendmailfun(); } I'm getting the the following error. com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.0 Must issue a STARTTLS command first Can anyone help me to rectify this?
import java.io.File; import java.io.IOException; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import org.testng.annotations.Test; public class SendAttachment{ #Test public static void sendmail() throws AddressException, MessagingException, InterruptedException{ Thread.sleep(50000); System.out.println("Test mail"); String[] to={"mail address","mail address"}; String to2="mail address";//change accordingly final String user="mail address";//change accordingly final String password="password";//change accordingly //1) get the session object Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", "smtp.gmail.com"); properties.put("mail.smtp.port", "587"); //TLS Port properties.put("mail.smtp.auth", "true"); //enable authentication properties.put("mail.smtp.starttls.enable", "true"); Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user,password); } }); //2) compose message MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(user)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("mailid1,mailid2")); message.setSubject("ECM Regression Test suite Results"); //3) create MimeBodyPart object and set your message text BodyPart messageBodyPart1 = new MimeBodyPart(); messageBodyPart1.setText("Please find the Regression Result in the attachment"); //4) create new MimeBodyPart object and set DataHandler object to this object MimeBodyPart messageBodyPart2 = new MimeBodyPart(); MimeBodyPart messageBodyPart3 = new MimeBodyPart(); MimeBodyPart messageBodyPart4 = new MimeBodyPart(); MimeBodyPart messageBodyPart5 = new MimeBodyPart(); File f3=new File("D:\\svn\\CI_1.0\\seleniumScriptsRegression\\seleniumScriptsRegression\\test-output\\emailable-report.html"); DataSource source4 = new FileDataSource(f3); messageBodyPart5.setDataHandler(new DataHandler(source4)); messageBodyPart5.setFileName(f3.getName()); //5) create Multipart object and add MimeBodyPart objects to this object Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart1); multipart.addBodyPart(messageBodyPart5); //6) set the multiplart object to the message object message.setContent(multipart); //7) send message Transport.send(message); System.out.println("message sent...."); } //} } Try to use like this its working for me. But When we run this old email able report only getting attached in the mail.
**You can send the mail through **Apache commons Email** ======================================================= **but before using Apache commons you need to add the dependency in Maven POM File.** Dependency is as mentioned below -------------------------------- <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-email --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-email</artifactId> <version>1.5</version> </dependency> You can refer to the below link for compatible dependency. **Link:** https://mvnrepository.com/artifact/org.apache.commons/commons-email **JAVA CODE** ------------ public void sendMail() throws MessagingException, EmailException { String username="abc.#gmail.com"; String password="1234567890"; String from_Email="xyz.#gmail.com"; String to_Email="pqr.#gmail.com"; Email email = new SimpleEmail(); email.setHostName("smtp.gmail.com"); email.setSmtpPort(465); email.setAuthenticator(new DefaultAuthenticator(username, password)); email.setSSLOnConnect(true); email.setFrom(from_Email); email.setSubject("This is a test mail ... :-)"); email.setMsg("Body Message"); email.addTo(to_Email); email.send(); }
Adding a signature to a certificate
I have some odd requirements that I have to live with. I need to pass my crypto system a TBS certificate, they will sign it and send back a String of the signature which I need to incorporate into a certificate to make a signed certificate. Looking at com.ibm.security.x509.X509CertImpl and various BouncyCastle posts on SO, I can't find out how to do that. Questions: Is this possible ? If so, how ?
I'd refer to the source code for the BouncyCastle X509v3CertificateBuilder class (pkix jar), and tweak it to suit your needs. Note that this class uses a V3TBSCertificateGenerator to produce the TBSCertificate. That's an ASN.1 object that you can DER encode. Then you can get the DER encoding signed by the "crypto system". Then consult X509v3CertificateBuilder.build() method as to how to put the TBS certificate and signature together into the final X.509 certificate.
I've put together an example that shows one way to do it. Most of this code was stolen from the bouncycastle pkix or lwcrypto libraries, but any bugs are almost certainly mine. The most important method to concentrate on below is generateCert. The rest of the code is test harness to drive the test. The code is specifically written to need only the bounycastle bcpkix and lwcrypto jars. It could be shortened somewhat if the bcprov jar was used instead of lwcrypto. import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.TBSCertificate; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.bc.BcX509v3CertificateBuilder; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; import javax.security.auth.x500.X500Principal; import java.io.ByteArrayInputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PublicKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPublicKey; import java.util.Date; public class Main { private static class TBSCertPlusSignature { private final byte[] encodedTbsCert; private final byte[] signature; public TBSCertPlusSignature(byte[] encodedTbsCert, byte[] signature) { this.encodedTbsCert = encodedTbsCert; this.signature = signature; } public byte[] getEncodedTbsCert() { return encodedTbsCert; } public byte[] getSignature() { return signature; } } private static TBSCertPlusSignature makeTestCert(KeyPair keyPair) throws Exception { Date now = new Date(); Date nowPlus1Hour = new Date(now.getTime() + 1000 * 60 * 60 * 1L); byte[] encodedName = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").getEncoded(); X500Name issuer = X500Name.getInstance(encodedName); X500Name subject = issuer; RSAPublicKey rsaPub = (RSAPublicKey) keyPair.getPublic(); RSAKeyParameters rsaPubParams = new RSAKeyParameters(false, rsaPub.getModulus(), rsaPub.getPublicExponent()); BcX509v3CertificateBuilder certBuilder = new BcX509v3CertificateBuilder( issuer, BigInteger.valueOf(100L), now, nowPlus1Hour, subject, rsaPubParams ); AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSA"); AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) keyPair.getPrivate(); RSAPrivateCrtKeyParameters rsaPrivParams = new RSAPrivateCrtKeyParameters( rsaPriv.getModulus(), rsaPriv.getPublicExponent(), rsaPriv.getPrivateExponent(), rsaPriv.getPrimeP(), rsaPriv.getPrimeQ(), rsaPriv.getPrimeExponentP(), rsaPriv.getPrimeExponentQ(), rsaPriv.getCrtCoefficient() ); ContentSigner contentSigner = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(rsaPrivParams); final X509CertificateHolder x509CertificateHolder = certBuilder.build(contentSigner); byte[] tbsCertDER = x509CertificateHolder.toASN1Structure().getTBSCertificate().getEncoded(); byte[] signature = x509CertificateHolder.getSignature(); return new TBSCertPlusSignature(tbsCertDER, signature); } private static X509Certificate generateCert(byte[] tbsCertEncoded, byte[] signature) throws Exception { // Given the der encoded TBS cert and signature, create the corresponding X509 certificate TBSCertificate tbsCert = TBSCertificate.getInstance(tbsCertEncoded); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCert); v.add(tbsCert.getSignature()); v.add(new DERBitString(signature)); DERSequence derSequence = new DERSequence(v); ByteArrayInputStream baos = new ByteArrayInputStream(derSequence.getEncoded()); return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(baos); } public static void main(String[] args) throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); KeyPair keyPair = kpg.generateKeyPair(); TBSCertPlusSignature testData = makeTestCert(keyPair); X509Certificate x509Cert = generateCert(testData.getEncodedTbsCert(), testData.getSignature()); // Verify the signature x509Cert.verify(keyPair.getPublic()); // Print the cert PublicKey publicKey = x509Cert.getPublicKey(); System.out.println(x509Cert); } }
Cannot unmarshal soap body to java object
This is related to my earlier post here getSOAPBody returns NULL whereas SOAPResponse.writeTo prints the whole message, Strange? I am posting my code that i am using to unmarshal. I receive all nulls in the target object package trials; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.Unmarshaller; import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPConnection; import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.transform.stream.StreamSource; public class SOAPClientSAAJ { public static void main(String args[]) throws Exception { // Create SOAP Connection SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); SOAPConnection soapConnection = soapConnectionFactory.createConnection(); // Send SOAP Message to SOAP Server String url = "http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx"; SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url); System.out.println("Body"); // print SOAP Response System.out.print("Response SOAP Message:"); System.out.println("SOAP Body 2= " + soapResponse.getSOAPBody()); System.out.println("SOAP Body 2=" + soapResponse.getSOAPPart().getEnvelope().getBody()); soapResponse.writeTo(System.out); SOAPBody body = soapResponse.getSOAPBody(); System.out.println("\n"); System.out.println(body.getElementsByTagName("ResponseText").item(0).getTextContent()); System.out.println(body.getElementsByTagName("ResponseCode").item(0).getTextContent()); System.out.println(body.getElementsByTagName("GoodEmail").item(0).getTextContent()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); soapResponse.writeTo(bos); XMLInputFactory xif = XMLInputFactory.newFactory(); StreamSource xml = new StreamSource(new ByteArrayInputStream(bos.toByteArray())); XMLStreamReader xsr = xif.createXMLStreamReader(xml); xsr.nextTag(); while (!xsr.getLocalName().equals("VerifyEmailResult")) { xsr.nextTag(); } JAXBContext jc = JAXBContext.newInstance(VerifyEmailResult.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); JAXBElement<VerifyEmailResult> jb = unmarshaller.unmarshal(xsr, VerifyEmailResult.class); xsr.close(); VerifyEmailResult v = jb.getValue(); System.out.println(v.ResponseText); System.out.println(v.ResponseCode); System.out.println(v.LastMailServer); System.out.println(v.GoodEmail); soapConnection.close(); } private static SOAPMessage createSOAPRequest() throws Exception { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage soapMessage = messageFactory.createMessage(); SOAPPart soapPart = soapMessage.getSOAPPart(); String serverURI = "http://ws.cdyne.com/"; // SOAP Envelope SOAPEnvelope envelope = soapPart.getEnvelope(); envelope.addNamespaceDeclaration("example", serverURI); /* * Constructed SOAP Request Message: <SOAP-ENV:Envelope * xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" * xmlns:example="http://ws.cdyne.com/"> <SOAP-ENV:Header/> * <SOAP-ENV:Body> <example:VerifyEmail> * <example:email>mutantninja#gmail.com</example:email> * <example:LicenseKey>123</example:LicenseKey> </example:VerifyEmail> * </SOAP-ENV:Body> </SOAP-ENV:Envelope> */ // SOAP Body SOAPBody soapBody = envelope.getBody(); SOAPElement soapBodyElem = soapBody.addChildElement("VerifyEmail", "example"); SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("email", "example"); soapBodyElem1.addTextNode("mutantninja#gmail.com"); SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("LicenseKey", "example"); soapBodyElem2.addTextNode("123"); MimeHeaders headers = soapMessage.getMimeHeaders(); headers.addHeader("SOAPAction", serverURI + "VerifyEmail"); soapMessage.saveChanges(); /* Print the request message */ System.out.print("Request SOAP Message:"); soapMessage.writeTo(System.out); System.out.println(); return soapMessage; } } Here is my class which i am trying to unmarshal to package trials; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; #XmlRootElement #XmlAccessorType(XmlAccessType.FIELD) public class VerifyEmailResult { public String ResponseText; public String ResponseCode; public String LastMailServer; public String GoodEmail; } Here is my console output Request SOAP Message:<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:example="http://ws.cdyne.com/"><SOAP-ENV:Header/><SOAP-ENV:Body><example:VerifyEmail><example:email>mutantninja#gmail.com</example:email><example:LicenseKey>123</example:LicenseKey></example:VerifyEmail></SOAP-ENV:Body></SOAP-ENV:Envelope> Body Response SOAP Message:SOAP Body 2= [soap:Body: null] SOAP Body 2=[soap:Body: null] <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><VerifyEmailResponse xmlns="http://ws.cdyne.com/"><VerifyEmailResult><ResponseText>Current license key only allows so many checks</ResponseText><ResponseCode>9</ResponseCode><LastMailServer/><GoodEmail>false</GoodEmail></VerifyEmailResult></VerifyEmailResponse></soap:Body></soap:Envelope> Current license key only allows so many checks 9 false null null null null
Try with response.response.getSOAPBody().extractContentAsDocument() I was facing the same problem and it is fixed with below code : SOAPMessage response = dispatch.invoke(request); Document document = response.getSOAPBody().extractContentAsDocument(); NodeList list = document.getChildNodes(); System.out.println("Value : " + list.item(0).getChildNodes().item(0).getChildNodes().item(0).getTextContent()); Hope this helps
How to change the default folder for uploading file in jboss
I am trying to upload a file, I am trying to change the default location of the uploaded file. How to change this please suggest ? package Controller; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; import requests.Connect; import display.DisplayLog; /** * Servlet implementation class ControlServlet */ public class ControlServlet extends HttpServlet{ private static final long serialVersionUID = 1L; boolean result; private boolean isMultipart; private String filePath; private int maxFileSize = 1000 * 1024; private int maxMemSize = 1000 * 1024; private File file ; public ControlServlet() { super(); // TODO Auto-generated constructor stub } /** * #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } /** * #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session=request.getSession(); String userName = request.getParameter("username"); isMultipart = ServletFileUpload.isMultipartContent(request); response.setContentType("audio/mpeg3;audio/x-mpeg-3;video/mpeg;video/x-mpeg;text/xml"); PrintWriter out = response.getWriter( ); if (isMultipart) { // Create a factory for disk-based file items FileItemFactory factory = new DiskFileItemFactory(); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); try { // Parse the request List items = upload.parseRequest(request); Iterator iterator = items.iterator(); while (iterator.hasNext()) { FileItem item = (FileItem) iterator.next(); if (!item.isFormField()) { String fileName = item.getName(); if (fileName != null) { fileName = FilenameUtils.getName(fileName); } String root = getServletContext().getRealPath("/"); root = "F/images"; File path = new File(root + "/uploads"); if (!path.exists()) { boolean status = path.mkdirs(); } File uploadedFile = new File(path + "/" + fileName); System.out.println(" Prashant File Upload Location is "); // System.out.println(uploadedFile.getAbsolutePath()); System.out.println("fileName is " +fileName); System.out.println("root is " + root); System.out.println("path is " + path); if(fileName!="") { item.write(uploadedFile); System.out.println(" Prashant File Upload Location 2 is "); System.out.println(uploadedFile.getAbsolutePath()); out.println("<h1>File Uploaded Successfully....:-)</h1>"); } else { out.println(uploadedFile.getAbsolutePath()); out.println("<h1>File Uploaded Successfully....:-)</h1>"); System.out.println("file not found"); } } else { String abc = item.getString(); } } } catch (FileUploadException e) { out.println(e); } catch (Exception e) { out.println(e); } } else { out.println("Not Multipart"); } System.out.println("print this Prashant" + userName); session.setAttribute("username",userName); request.setAttribute("username","prashant"); // RequestDispatcher myDispatch = request.getRequestDispatcher("Index.jsp"); //myDispatch.forward(request, response); } } I am getting this as default folder F:\jboss-4.2.3.GA-jdk6\jboss-4.2.3.GA\bin\ please help i am new to this
Your problem is here: String root = getServletContext().getRealPath("/"); you are setting the upload path to the containers path, not a default path but the place where the server started from. You can make the upload path anything you want it to be, it depends on your needs and configuration. You could create a system property with the directory of your choice, you could set it as a dynamic property in a JBoss configuration file (not sure what that would be for JBoss4).