Created
January 28, 2015 08:32
-
-
Save pvillega/9271089849176fdfff0a to your computer and use it in GitHub Desktop.
BAPI request sign steps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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