package com.github.bingoohuang.springrestclient.spring.aliyun.utils;
import com.github.bingoohuang.springrestclient.ext.ParameterDelayable;
import lombok.SneakyThrows;
import lombok.val;
import org.n3r.diamond.client.Miner;
import org.springframework.stereotype.Component;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.net.URLEncoder;
import java.util.Map;
import java.util.TreeMap;
@Component
public class PubParamsSignature implements ParameterDelayable {
public static final String HMAC_SHA1 = "HmacSHA1";
@Override
public String computeDelayedParam(Map<String, Object> mergedRequestParams) {
val sortedMap = new TreeMap<String, Object>(mergedRequestParams);
val sb = new StringBuilder();
for (Map.Entry<String, Object> entry : sortedMap.entrySet()) {
sb.append(urlEncode(entry.getKey())).append("=")
.append(urlEncode("" + entry.getValue())).append("&");
}
if (sb.length() > 0) sb.setLength(sb.length() - 1); // remove last &
val canonicalizedQueryString = sb.toString();
val stringToSign = percentEncode("GET&/&") + urlEncode(canonicalizedQueryString);
val hamcKey = getAccessSecret() + "&";
val signature = hmacSHA1(stringToSign, hamcKey);
return signature;
}
@SneakyThrows
public String hmacSHA1(String data, String key) {
val keySpec = new SecretKeySpec(key.getBytes(), HMAC_SHA1);
val mac = Mac.getInstance(HMAC_SHA1);
mac.init(keySpec);
val bytes = mac.doFinal(data.getBytes());
return DatatypeConverter.printBase64Binary(bytes);
}
private String getAccessSecret() {
val miner = new Miner().getMiner("aliyun", "rds");
return miner.getString("access_secret");
}
private String percentEncode(String str) {
return str.replace("/", "%2F");
}
@SneakyThrows
private String urlEncode(String val) {
String encoded = URLEncoder.encode(val, "UTF-8");
return encoded
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E", "~");
}
}