1. 程式人生 > >阿里雲實人認證生成簽名SignNature工具類

阿里雲實人認證生成簽名SignNature工具類

  此類是有時間寫的,使用阿里雲給出的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);
	}
}