API网关计算签名的方法

拼接签名内容
 
API网关在计算签名前,需要按照以下格式生成签名原文:
 
String strToSign =
    HttpMethod + "\n" +
    URI + "\n" +
    Headers + "\n" +
    ContentDigest
 
拼接格式说明:
参数说明
 
HttpMethod
API的调用方法,如GET、POST等。
 
URI
 
API的请求路径,格式为Path + Query:
 
String url =
    Path +
    "?" +
    Key1 + "=" + Value1 +
    "&" + Key2 + "=" + Value2 +
    ...
    "&" + KeyN + "=" + ValueN;
 
其中:
 
•   Path:如果有非法字符,例如:中文等,需要根据 Percent-Encoding使用UTF-8字符集对其进行编码。
 
•   Query:先对参数的名称即Key按照字典顺序排序,再按照如下方法进行拼接:
 
    ♦   如果参数为空,则 URL = Path,不需要添加"?"。
 
    ♦   如果某个参数的Value为空,则只保留参数的Key参与计算签名,等号 = 不需要再加入签名。
 
    ♦   如果某个参数的Value存在多个,则多个Value需要按照字典顺序进行排序后参与签名计算。
 
        例如:String url = "/some/path.html?key1=value1&key2=value2&key2=value3&key3"
 
Query中参数的Key和Value是未进行URLEncoding的原数据。
 
Headers
 
由参与签名计算的请求头中参数的Key、Value拼接而成的字符串。参与签名计算的请求头包括:PA-AG-Gateway-Timestamp以及PA-AG-Gateway-Signature-Headers。
 
请求头不区分大小写。
 
Headers拼接方式:
 
先对参与签名计算的请求头中参数的 Key 按照字典顺序排序,再按照如下方式进行拼接:
 
•   如果请求头中某个参数的Value为空,则使用HeaderKey.toLowercase() + ":"参与签名,需要保留Key和英文冒号":",并且Key和Value左右两边不能有空白字符。
 
•   如果请求头中某个参数的Value存在多个,多个Value需要按照字典顺序进行排序后参与签名计算。
 
例如:
 
String headers =
    HeaderKey1.toLowercase() + ":" + HeaderValue1.toLowercase() + "\n"\+
    HeaderKey2.toLowercase() + ":" + HeaderValue2.toLowercase() + "\n"\+
    ...
    HeaderKeyN.toLowercase() + ":" + HeaderValueN.toLowercase() + "\n"
 
ContentDigest
 
请求体的MD5值。
 
存在请求体时,需要对请求体进行MD5转码。
 
计算方式:
 
String contentDigest = Base64.encodeBase64(MD5(requestBody.getbytes("UTF-8")));
 
生成签名结果
 
API网关生成签名原文后,通过签名密钥,按照设置的签名算法进行签名计算。
 
签名计算方法:
 
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] keyBytes = secret.getBytes("UTF-8");
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
String sign = new String(Base64.encodeBase64(hmacSha256.doFinal(strToSign.getBytes("UTF-8")),"UTF-8"));
 
其中:
 
•   secret:是绑定到API上的签名密钥的Secret。
 
•   签名算法:是创建API时选择的签名算法类型,目前支持HmacSHA1和HmacSHA256两种。
 
传递签名结果
 
按照设置的签名算法进行签名计算后,API网关将签名结果放到PA-AG-Gateway-Signature字段中,并将在计算过程中所使用的签名密钥的Key放到PA-AG-Gateway-Sign-Key字段中。