0
votes

I am load testing an API using Jmeter. The Header of the request has an authentication request which needs me to Base64 the url+Nonce+Unix timestamp and SHA256 the resultant value with a secret key. The above needs to be passed in header along with Nonce and timestamp.

For the above scenario should I create a custom function or use any preprocessor ?

4
I didn't ask for program, I am just asking what would be the best way to go! - irarelyask

4 Answers

3
votes

You can do it via Beanshell PreProcessor as follows:

  1. Add a HTTP Header Manager as a child of your HTTP Request sampler
  2. Add aforementioned Beanshell PreProcessor the same way
  3. Put the following code into the PreProcessor's "Script" area:

    import org.apache.commons.httpclient.auth.DigestScheme; // necessary imports
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.codec.digest.DigestUtils;
    import org.apache.jmeter.protocol.http.control.Header;
    
    String url = sampler.getUrl().toString(); // get URL
    String nonce = DigestScheme.createCnonce(); // get nonce
    long timestamp = System.currentTimeMillis() / 1000L;
    
    String combined = url + nonce + timestamp; // put everything together
    
    byte[] base64 = Base64.encodeBase64(combined.getBytes()); // encode as Base64
    
    String headerValue = DigestUtils.sha256Hex(base64); // encode SHA256 
    
    sampler.getHeaderManager().add(new Header("headerName", headerValue)); // add generated header to request
    
    • sampler here is a shorthand reference to parent HTTP Request Sampler class which I believe is HTTPSamplerProxy so its methods are used to get URL and add generated header value.
    • methods to generate MD5 hash and SHA256 hex are from Apache Commons libraries which are widely used under JMeter's hood.

See How to use BeanShell: JMeter's favorite built-in component guide for more information on using Beanshell scripting in JMeter tests.

0
votes

Your best bet is to use a BSF Pre-Processor in JavaScript mode to do everything the client normally would. You'll have to take the client JS and modify it to work without FORM data.

You can build the entire header in JS exactly like a client would. BSF Pre-Processor allows you to access jmeter run-time variables, so you would create a new one to store the SHA256 hash value, and use that in a HTTP Header Manager of the sample that needs the authorization.

-Addled

0
votes

Downloaded eclipse. Wrote a custom jmeter package. Exported it as a .jar from eclipse to jmeter lib/ext folder. Called the package function in beanshell sampler

Thanks for your answers

0
votes

@dmitrit's answer is helpful but I needed to do some tweaks to the code to get it to work. Here is what I did:

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

String apiKey = vars.get("ApiKey");
String apiSecret = vars.get("ApiSecret");
long timestamp = System.currentTimeMillis() / 1000L;

String combined = apiKey + apiSecret + timestamp;

String generatedSignature = DigestUtils.sha256Hex(combined);

vars.put("GeneratedSignature", generatedSignature);

Note the main differences are:

  • Most important: DigestUtils.sha256Hex takes a String instead of a byte array. Converting first to bytes screwed up the hash, I think due to padding.
  • I added the resulting value to vars so it can be used later in Jmeter in the usual way (${GeneratedSignature}).
  • ApiKey and ApiSecret are defined elsewhere in a Jmeter User Defined Variables element.

With this I was able to make the following work with Mashery in accordance with their authentication instructions posted here.