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(" "+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(" "+Signature); 54 55 // 注意:得到的签名值在作为最后的请求参数值提交给 DirectMail 服务器的时候,要和其他参数一样,按照 RFC3986 的规则进行 URL 编码)。 56 System.out.println(" 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
看了几天,对短信服务的签名做了测试,终于和提供的一致了