Java签名算法参考
签名代码:UrlUtil.java
import java.net.URLEncoder;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
public class UrlUtil {
private static Logger logger = Logger.getLogger(UrlUtil.class);
private final static String CHARSET_UTF8 = "utf8";
/**
*
* @param url
* @return
*/
public static String urlEncode(String url) {
if (!StringUtils.isEmpty(url)) {
try {
url = URLEncoder.encode(url, "UTF-8");
} catch (Exception e) {
logger.warn("Url encode error:" + e.getMessage());
}
}
return url;
}
public static String generateQueryString(Map<String, String> params, boolean isEncodeKV) {
StringBuilder canonicalizedQueryString = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (isEncodeKV)
canonicalizedQueryString.append(percentEncode(entry.getKey())).append("=")
.append(percentEncode(entry.getValue())).append("&");
else
canonicalizedQueryString.append(entry.getKey()).append("=")
.append(entry.getValue()).append("&");
}
if (canonicalizedQueryString.length() > 1) {
canonicalizedQueryString.setLength(canonicalizedQueryString.length() - 1);
}
return canonicalizedQueryString.toString();
}
public static String percentEncode(String value) {
try {
// 使用URLEncoder.encode编码后,将"+","*","%7E"做替换即满足 API规定的编码规范
return value == null ? null : URLEncoder.encode(value, CHARSET_UTF8)
.replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
} catch (Exception e) {
//不可能发生的异常
}
return "";
}
}
SignatureUtils.java
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
public class SignatureUtils {
private final static String CHARSET_UTF8 = "utf8";
private final static String ALGORITHM = "UTF-8";
private final static String SEPARATOR = "&";
public static Map<String, String> splitQueryString(String url)
throws URISyntaxException, UnsupportedEncodingException {
URI uri = new URI(url);
String query = uri.getQuery();
final String[] pairs = query.split("&");
TreeMap<String, String> queryMap = new TreeMap<String, String>();
for (String pair : pairs) {
final int idx = pair.indexOf("=");
final String key = idx > 0 ? pair.substring(0, idx) : pair;
if (!queryMap.containsKey(key)) {
queryMap.put(key, URLDecoder.decode(pair.substring(idx + 1), CHARSET_UTF8));
}
}
return queryMap;
}
public static String generate(String method, Map<String, String> parameter,
String accessKeySecret) throws Exception {
String signString = generateSignString(method, parameter);
System.out.println("signString---"+signString);
byte[] signBytes = hmacSHA1Signature(accessKeySecret + "&", signString);
String signature = newStringByBase64(signBytes);
System.out.println("signature---"+signature);
if ("POST".equals(method))
return signature;
return URLEncoder.encode(signature, "UTF-8");
}
public static String generateSignString(String httpMethod, Map<String, String> parameter)
throws IOException {
TreeMap<String, String> sortParameter = new TreeMap<String, String>();
sortParameter.putAll(parameter);
String canonicalizedQueryString = UrlUtil.generateQueryString(sortParameter, true);
if (null == httpMethod) {
throw new RuntimeException("httpMethod can not be empty");
}
StringBuilder stringToSign = new StringBuilder();
stringToSign.append(httpMethod).append(SEPARATOR);
stringToSign.append(percentEncode("/")).append(SEPARATOR);
stringToSign.append(percentEncode(canonicalizedQueryString));
return stringToSign.toString();
}
public static String percentEncode(String value) {
try {
return value == null ? null : URLEncoder.encode(value, CHARSET_UTF8)
.replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
} catch (Exception e) {
}
return "";
}
public static byte[] hmacSHA1Signature(String secret, String baseString)
throws Exception {
if (StringUtils.isEmpty(secret)) {
throw new IOException("secret can not be empty");
}
if (StringUtils.isEmpty(baseString)) {
return null;
}
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(CHARSET_UTF8), ALGORITHM);
mac.init(keySpec);
return mac.doFinal(baseString.getBytes(CHARSET_UTF8));
}
public static String newStringByBase64(byte[] bytes)
throws UnsupportedEncodingException {
if (bytes == null || bytes.length == 0) {
return null;
}
return new String(Base64.encodeBase64(bytes, false), CHARSET_UTF8);
}
public static void main(String[] args) {
String str = "GET&%2F&AccessKeyId%3DCd***eHJuMOrT%26Action%3DDescribeInstances%26Format%3DJSON%26RegionId%3Dcn-hangzhou%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D9fdf288**36082ebef%26SignatureVersion%3D1.0%26Timestamp%3D2015-12-21T09%253A05%253A44Z%26Version%3D2014-05-26";
byte[] signBytes;
try {
signBytes = SignatureUtils.hmacSHA1Signature("byc****6HQmH" + "&", str.toString());
String signature = SignatureUtils.newStringByBase64(signBytes);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//测试代码
private static String getQueryUrl(Map<String, String> param) throws Exception {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
simpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
String timestamp = simpleDateFormat.format(date);
Map<String, String> publicParam = Maps.newHashMap();
publicParam.put("AccessKeyId", accessKeyId);
publicParam.put("Format", "json");
publicParam.put("SignatureMethod", "Hmac-SHA1");
publicParam.put("SignatureNonce", UUID.randomUUID().toString());
publicParam.put("SignatureVersion", "1.0");
publicParam.put("Timestamp", timestamp);
publicParam.put("Version", "2014-05-15");
publicParam.put("RegionId", "cn-shanghai");
if (param != null) {
for (Map.Entry<String, String> entry : param.entrySet()) {
publicParam.put(entry.getKey(), entry.getValue());
}
}
String s = SignatureUtils.generateSignString("GET", publicParam);
byte[] signBytes;
signBytes = SignatureUtils.hmacSHA1Signature(secret + "&", s);
String signature = SignatureUtils.newStringByBase64(signBytes);
publicParam.put("signature", signature);
String url = "http://slb.aliyuncs.com/?";
//对参数进行url编码
for (Map.Entry<String, String> entry : publicParam.entrySet()) {
publicParam.put(entry.getKey(), URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
}
//拼接请求url
for (Map.Entry<String, String> entry : publicParam.entrySet()) {
url = url + entry + "&";
}
//去掉最后一个&
url = url.substring(0, url.length() - 1);
return url;
}
public static void main(String[] args) {
try {
Map<String, String> map = Maps.newHashMap();
map.put("Action", "DescribeLoadBalancerAttribute");
map.put("LoadBalancerId", "lb-********");
String url = getQueryUrl(map);
System.err.println("\n" + url);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
参考 https://help.aliyun.com/document_detail/28618.html