-
在请求阿里云的http接口,没有sdk的情况下,我们需要自己手动拼接公共参数,并且做签名。但是阿里云官方的文档写的可能有点乱或者是我自己能力不太够,反正我是看的一脸懵,所以我在他给的基础上,自己手动封装了一些方法。
-
先上一些工具方法
1.hmacSHA1签名工具
private static byte[] hmacSHA1Signature(String accessKeySecret, String stringToSign) {
try {
String key = accessKeySecret + "&";
try {
SecretKeySpec signKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signKey);
return mac.doFinal(stringToSign.getBytes());
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
} catch (SignatureException e) {
e.printStackTrace();
}
return null;
}
2.base64数组转字符串
private static String newStringByBase64(byte[] bytes)
throws UnsupportedEncodingException {
if (bytes == null || bytes.length == 0) {
return null;
}
return new String(Base64.getEncoder().encode(bytes));
}
- 这里的Base64是java.util.Base64,阿里云官方的文档可能在JDK8以后支持不是很好。具体怎么个不好,自己试试就知道了。
3.特殊字符串转义方法
private static String percentEncode(String value) {
try {
String urlEncodeOrignStr = URLEncoder.encode(value, "UTF-8");
String plusReplaced = urlEncodeOrignStr.replace("+", "%20");
String starReplaced = plusReplaced.replace("*", "%2A");
String waveReplaced = starReplaced.replace("%7E", "~");
return waveReplaced;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return value;
}
- 以上三个方法都是阿里云官方提供的,我也没有修改,可以直接使用。
4.公共参数拼接
private static JSONObject commonParams() {
JSONObject result = new JSONObject();
String SignatureNonce = Utils.generateId();
String format = "JSON";
String SignatureMethod = "HMAC-SHA1";
String SignatureVersion = "1.0";
String timestamp = DateUtil.getAliTimestamp(new Date());
result.put("SignatureMethod", SignatureMethod);
result.put("SignatureNonce", SignatureNonce);
result.put("SignatureVersion", SignatureVersion);
result.put("AccessKeyId", accessKeyId);
result.put("Timestamp", timestamp);
result.put("Format", format);
result.put("Version", "2017-03-21");
return result;
}
5.签名参数排序
private static List<String> paramsSort(List<String> keys) {
Collections.sort(keys);
return keys;
}
6.主题:所有参数进行签名
public static JSONObject commonParams(String httpMethod, JSONObject params) throws CoreServiceException {
// 获取公共参数
JSONObject commonParams = commonParams();
// 获取需要签名的参数,需要把公共参数和接口请求参数全部做签名
JSONObject signParams = new JSONObject();
signParams.putAll(commonParams);
signParams.putAll(params);
// 对所有参数的key进行排序
Set<String> keySet = signParams.keySet();
List<String> keys = new ArrayList<>();
for (String key : keySet) {
keys.add(key);
}
StringBuilder stringToSign = new StringBuilder();
keys = paramsSort(keys);
// 遍历生成需要签名的字符串
for (String key : keys) {
stringToSign.append("&");
stringToSign.append(key);
stringToSign.append("=");
stringToSign.append(percentEncode(signParams.getString(key)));
}
String string = stringToSign.toString();
String StringToSign = httpMethod + "&" + percentEncode("/") + "&" + percentEncode(string.substring(1));
String sign = "";
try {
sign = newStringByBase64(hmacSHA1Signature(accessKeySecret, StringToSign));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if(StringUtils.isEmpty(sign)) {
throw new CoreServiceException(OrgExceptype.DEFAULT, "阿里签名失败,请重试");
}
// 将签名放到公共参数中返回给需要的地方
commonParams.put("Signature", sign);
return commonParams;
}
- 这样我们就可以拿到阿里需要的公共参数了,基本和阿里官方的类似,但是有的地方做过一些改进,可能适合我自己的项目,大家做个参考。