阿里雲實人認證生成簽名SignNature工具類
阿新 • • 發佈:2019-01-22
此類是有時間寫的,使用阿里雲給出的demo測試正確。實際在呼叫阿里雲的實人認證介面時並未用到,可直接整合相關的sdk。
程式碼
package cn.com.chnsys.utils; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; /** * * <p> * 類描述 生成阿里雲signNature工具類 * </p> * * 類說明 * * @author yyb * @version 1.0 */ public class GenerateSignUtil { public static String generateSignNature(Map<String, String> map) throws Exception { // 1.構建待簽名字串 // 1.1.按照引數名稱的字典順序對請求中所有的請求引數 Set<String> keySet = map.keySet(); List<String> list = new ArrayList<>(); list.addAll(keySet); List<String> sortList = sort(list); // 1.2.對排序之後的請求引數的名稱和值分別用UTF-8字符集進行URL編碼 // 1.3.將編碼後的引數名稱和值用英文等號(=)進行連線 // 1.4. 將等號連線得到的引數組合按步驟1.1排好的順序依次使用“&”符號連線,即得到規範化請求字串 StringBuffer sb = new StringBuffer(); for (int i = 0; i < sortList.size(); i++) { String key = sortList.get(i); //注:這裡應該比較low。在測試過程中發現 冒號:最終會被編碼會 “%253A”,是經過了兩次。有好的方法請告知 if (key.equals("Timestamp")) { sb.append(AcsURLEncoder.percentEncode(key)).append("=") .append(AcsURLEncoder.percentEncode(AcsURLEncoder.percentEncode(map.get(key)))).append("&"); } else { sb.append(AcsURLEncoder.percentEncode(key)).append("=") .append(AcsURLEncoder.percentEncode(map.get(key))).append("&"); } } String sign = sb.toString(); String temp = sign.substring(0, sign.length() - 1); System.out.println(temp); // 1.5.待簽名的字串 String stringToSign = "GET&" + AcsURLEncoder.percentEncode("/") + "&" + temp.replace("=", "%3D"); // 2.計算簽名 // 2.1.HMAC值 byte[] hmacSha1 = HmacSha1(stringToSign, "testsecret&"); // 2.2.Base64編碼 String result = Base64Encode(hmacSha1); // 2.3.返回 return result; } private static List<String> sort(List<String> list) { if (list != null && list.size() > 0) { Collections.sort(list); } return list; } /** * 生成hmacsha1簽名 * * @param binaryData * @param key * @return * @throws Exception */ public static byte[] HmacSha1(byte[] binaryData, String key) throws Exception { Mac mac = Mac.getInstance("HmacSHA1"); SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA1"); mac.init(secretKey); byte[] HmacSha1Digest = mac.doFinal(binaryData); return HmacSha1Digest; } /** * 生成hmacsha1簽名 * * @param plainText * @param key * @return * @throws Exception */ public static byte[] HmacSha1(String plainText, String key) throws Exception { return HmacSha1(plainText.getBytes("UTF-8"), key); } /** * 生成base64編碼 * * @param binaryData * @return */ public static String Base64Encode(byte[] binaryData) { String encodedstr = Base64.getEncoder().encodeToString(binaryData); return DatatypeConverter.printBase64Binary(binaryData); } /** * 測試 * @param args * @throws Exception */ public static void main(String[] args) throws Exception { //阿里雲的demo String url = "http://ecs.aliyuncs.com/?Timestamp=2016-02-23T12:46:24Z&Format=XML&AccessKeyId=testid&Action=DescribeRegions&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2014-05-26&SignatureVersion=1.0"; //阿里雲的結果:VyBL52idtt+oImX0NZC+2ngk15Q= 用於對比我們的結果 Map<String, String> map = new HashMap<>(); map.put("Timestamp", "2016-02-23T12:46:24Z"); map.put("Format", "XML"); map.put("AccessKeyId", "testid"); map.put("Action", "DescribeRegions"); map.put("SignatureMethod", "HMAC-SHA1"); map.put("SignatureNonce", "3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf"); map.put("Version", "2014-05-26"); map.put("SignatureVersion", "1.0"); String result = generateSignNature(map); System.out.println(result); } }