1 @org.junit.Test 2 public void testA(){ 3 try { 4 Map<String,String> param=new HashMap<String,String>(); 5 param.put("AccessKeyId","testid"); 6 param.put("Action","SingleSendSms"); 7 param.put("ParamString","{\"name\":\"d\",\"name1\":\"d\"}"); 8 param.put("RecNum","13098765432"); 9 param.put("RegionId","cn-hangzhou"); 10 param.put("SignName","標簽測試"); 11 param.put("SignatureMethod","HMAC-SHA1"); 12 param.put("SignatureNonce","9e030f6b-03a2-40f0-a6ba-157d44532fd0"); 13 param.put("SignatureVersion","1.0"); 14 param.put("TemplateCode","SMS_1650053"); 15 param.put("Timestamp","2016-10-20T05:37:52Z"); 16 param.put("Version","2016-09-27"); 17 param.put("Format","XML"); 18 //構造規范化請求字符串Canonicalized Query String 19 StringBuffer cqs=new StringBuffer(); 20 // 按照參數名稱的字典順序對請求中所有的請求參數進行排序。(不包括簽名字符串參數) 21 String[] keyArray = (String[])param.keySet().toArray(new String[]{}); 22 Arrays.sort(keyArray); 23 // 對每個請求參數的名稱和值進行編碼。名稱和值要使用 UTF-8 字符集進行 URL編碼 24 // 一般支持 URL 編碼的庫(比如 Java 中的 java.net.URLEncoder) 25 // 都是按照“application/x-www-form-urlencoded”的MIME類型的規則進行編碼的。實現時可以直接使用這類方式進行編碼, 26 // 把編碼后的字符串中加號(+)替換成%20、星號(*)替換成%2A、%7E 替換回波浪號(~) 27 28 // 對編碼后的參數名稱和值使用英文等號(=)進行連接。 29 // 再把英文等號連接得到的字符串按參數名稱的字典順序依次使用&符號連接,即得到規范化請求字符串。 30 for (int i = 0; i < keyArray.length; i++) { 31 cqs.append(percentEcoding(keyArray[i])).append("=") 32 .append(percentEcoding(param.get(keyArray[i]))); 33 if(i<keyArray.length-1){ 34 cqs.append("&"); 35 } 36 } 37 // 使用上一步構造的規范化字符串按照下面的規則構造用於計算簽名的字符串: 38 StringBuffer StringToSign=new StringBuffer(); 39 StringToSign.append("POST").append("&").append(percentEcoding("/")).append("&").append(percentEcoding(cqs.toString())); 40 //打印StringToSign 41 System.out.println("\n"+StringToSign.toString()); 42 43 // 按照 RFC2104 的定義,使用上面的用於簽名的字符串計算簽名 HMAC 值。 44 // 注意:計算簽名時使用的 Key 就是用戶持有的 Access Key Secret 並加上一個“&”字符(ASCII:38),使用的哈希算法是 SHA1。 45 String signKey="testsecret&"; 46 String dig="HmacSHA1"; 47 Mac mac=Mac.getInstance(dig); 48 mac.init(new SecretKeySpec(signKey.getBytes("utf-8"),dig)); 49 byte[] doFinal = mac.doFinal(StringToSign.toString().getBytes("utf-8")); 50 // 按照 Base64 編碼規則把上面的 HMAC 值編碼成字符串,即得到簽名值(Signature)。 51 String Signature=Base64Helper.encode(doFinal);//阿里雲的SDK提供的工具類 52 //打印Signature 53 System.out.println("\n "+Signature); 54 55 // 注意:得到的簽名值在作為最后的請求參數值提交給 DirectMail 服務器的時候,要和其他參數一樣,按照 RFC3986 的規則進行 URL 編碼)。 56 System.out.println("\n ecode "+preEcode(Signature)); 57 } catch (UnsupportedEncodingException e) { 58 e.printStackTrace(); 59 } catch (NoSuchAlgorithmException e) { 60 e.printStackTrace(); 61 } catch (InvalidKeyException e) { 62 e.printStackTrace(); 63 } 64 } 65 public String percentEcoding(String value) throws UnsupportedEncodingException{ 66 return value!=null?URLEncoder.encode(value, "utf-8").replace("+", "%20").replace("*", "%2A") 67 .replace("%7E", "~"):null; 68 } 69
看了幾天,對短信服務的簽名做了測試,終於和提供的一致了