Skip to content

Instantly share code, notes, and snippets.

@pvillega
Created January 28, 2015 08:32
Show Gist options
  • Save pvillega/9271089849176fdfff0a to your computer and use it in GitHub Desktop.
Save pvillega/9271089849176fdfff0a to your computer and use it in GitHub Desktop.
BAPI request sign steps
public void signRequest(Request request) {
if (apiKey != null) {
try {
request.queryParameter(API_KEY_NAME, bapiKey);
request.queryParameter(TIMESTAMP_NAME, String.valueOf(System.currentTimeMillis()));
request.queryParameter(SIGNATURE_NAME, sign(getSignablePart(request), apiKey.getPrivateKey()));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
private String sign(String url, String privateKey) throws NoSuchAlgorithmException, InvalidKeyException {
SecretKey key = new SecretKeySpec(privateKey.getBytes(), "hmacSHA256");
Mac m = Mac.getInstance("hmacSHA256");
m.init(key);
m.update(url.getBytes());
return new String(Hex.encode(m.doFinal()));
}
private String getSignablePart(SignableRequest request) {
StringBuilder builder = new StringBuilder(request.getRequestPath());
String queryString = request.getQueryString(new NameValuePairSorter());
if (StringUtils.hasLength(queryString)) {
builder.append("?").append(queryString);
}
return builder.toString().toLowerCase();
}
private String getSignablePart(Request request) throws Exception {
UriBuilderImpl uriBuilder = ClientRequestUriExtractor.extractUri(request);
URI uri = null;
if (request.getMatrixParameters() != null) {
for (Map.Entry<String, List<String>> entry : request.getMatrixParameters().entrySet()) {
List<String> values = entry.getValue();
for (String value : values) {
uriBuilder.matrixParam(entry.getKey(), value);
}
}
}
if (request.getQueryParameters() != null) {
for (Map.Entry<String, List<String>> entry : request.getQueryParameters().entrySet()) {
List<String> values = entry.getValue();
for (String value : values) {
uriBuilder.clientQueryParam(entry.getKey(), value);
}
}
}
if (request.getPathParameterList() != null && !request.getPathParameterList().isEmpty()){
uri = uriBuilder.build(request.getPathParameterList().toArray());
} else if (request.getPathParameters() != null && !request.getPathParameters().isEmpty()) {
for (Map.Entry<String, List<String>> entry : request.getPathParameters().entrySet())
{
List<String> values = entry.getValue();
for (String value : values)
{
value = Encode.encodePathAsIs(value);
uriBuilder.substitutePathParam(entry.getKey(), value, true);
}
}
}
if (uri == null) {
uri = uriBuilder.build();
}
SignableRequest signableRequest = new SignableURI(uri);
return getSignablePart(signableRequest);
}
private static class NameValuePairSorter implements Comparator<NameValuePair> {
@Override
public int compare(NameValuePair o1, NameValuePair o2) {
int result = o1.getName().compareTo(o2.getName());
if (result == 0) {
result = o1.getValue().compareTo(o2.getValue());
}
return result;
}
}
public final class SecurityUtils {
public static final String ACCESS_KEY = "apiKey";
public static final String TIMESTAMP = "timestamp";
public static final String SIGNATURE = "signature";
public static final String AUTHENTICATION_ENABLED = "authentication";
private static final String API_SIGNATURE_ALGORITHM = "hmacSHA256";
/**
* Create an api signature given a request and private key.
*
* @param request the source request
* @param privateKey the private key
* @return an api signature given a request and private key.
* @throws NoSuchAlgorithmException when algorithm can't be found
* @throws InvalidKeyException when the key is invalid
*/
public static String createApiRequestSignature(ServletRequest request, String privateKey)
throws NoSuchAlgorithmException, InvalidKeyException {
Assert.notNull(request);
Assert.notNull(privateKey);
return signUrl(normaliseUrl(request), privateKey);
}
public static String signUrl(String url, String privateKey)
throws NoSuchAlgorithmException, InvalidKeyException {
Assert.notNull(url);
Assert.notNull(privateKey);
SecretKey key = new SecretKeySpec(privateKey.getBytes(), API_SIGNATURE_ALGORITHM);
Mac m = Mac.getInstance(API_SIGNATURE_ALGORITHM);
m.init(key);
m.update(url.getBytes());
return new String(Hex.encode(m.doFinal()));
}
public static String normaliseUrl(ServletRequest request) {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
String uri = httpRequest.getRequestURI().toLowerCase();
Map<String, String[]> parameters = Maps.newHashMap(request.getParameterMap());
parameters.remove(SIGNATURE);
if (parameters.size() > 0) {
List<KeyValuePair<String, String>> parameterPairs = Lists.newArrayList();
// lowercase params/values
for (String name : parameters.keySet()) {
for (String value : parameters.get(name)) {
parameterPairs.add(new KeyValuePair<String, String>(name.toLowerCase(), value.toLowerCase()));
}
}
// sort params/values
Collections.sort(parameterPairs, new KeyValuePairComparator());
// join key/value pairs
Function<KeyValuePair<String, String>, String> keyValuePairJoiner =
new Function<KeyValuePair<String, String>, String>() {
@Override
public String apply(KeyValuePair<String, String> pair) {
return Joiner.on("=").join(pair.getKey(), pair.getValue());
}
};
// join entire query string
String query = Joiner.on("&").join(Collections2.transform(parameterPairs, keyValuePairJoiner));
uri = Joiner.on("?").join(uri, query);
}
return uri;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment