加签机制
系统级Header
- 【必选】x-ca-key:AppKey。
- 【必选】x-ca-signature:签名字符串。
- 【可选】x-ca-timestamp:API调用者传递时间戳,值为当前时间的毫秒数,即从1970年1月1日起至今的时间转换为毫秒。时间戳有效时间为15分钟。
- 【可选】x-ca-nonce:API调用者生成的UUID,结合时间戳防重复。
签名校验
-
构建加密字符串。
String stringToSign=
HTTPMethod + "\n" +
Accept + "\n" + //建议显示设置Accept Header。当Accept为空时,部分Http客户端给Accept设置默认值*/*,会导致签名校验失败
Content-MD5 + "\n"
Content-Type + "\n" +
Date + "\n" +
Headers +
Url其中,HTTPMethod为全大写,如:POST。Accept、Content-MD5、Content-Type、Date如果为空也需要添加换行符\n;Headers如果为空不需要添加\n。
-
Accept:
Accept请求HTTP标头表示客户端能够理解的内容类型,以MIME类型的形式表达。语法为:
<MIME_type>/<MIME_subtype> //eg: application/json
-
Content-Type:
Content-Type表示标头用于指示资源的原始媒体类型(在发送时应用任何内容编码之前)。在响应中,Content-Type标头向客户端提供返回内容的实际内容类型。语法举例为:
Content-Type: text/html; charset=utf-8
-
Content-MD5:
Content-MD5是指Body的MD5值,只有当Body非Form表单时才计算 MD5,计算方式如下:
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8"))); //bodyStream为字节数组
-
Headers:
Headers是指参与签名计算的Header的Key、Value拼接的字符串,建议对 X-Ca 开头的Header和自定义Header计算签名。
说明: 以下参数不参与Headers签名计算:x-ca-signature、x-ca-signature-headers、Accept、Content-MD5、Content-Type、Date。
Headers组织方法如下:
对参与签名计算的Header的Key按照字典排序后使用。如果某个Header的Value为空,则使用HeaderKey + “:”+“\n”参与签名,需要保留Key和英文冒号。示例如下所示:
String headers =
HeaderKey1 + ":" + HeaderValue1 + "\n"\+
HeaderKey2 + ":" + HeaderValue2 + "\n"\+
...HeaderKeyN + ":" + HeaderValueN + "\n"此外,还需要将所有参与签名的Header的key拼接到一起(用英文逗号分隔,假设此处拼接得到的字符串为Key1,Key2,Key3),且在调用API的HTTP Request中添加对应的Header项,即X-Ca-Signature-Headers:Key1,Key2,Key3。
-
URL:
URL指Path+Query+Body中Form参数,组织方法如下:
对Query+Form参数按照字典对Key进行排序后,按照如下方法拼接,如果Query或Form参数为空,则URL=Path,不需要添加,如果某个参数的Value为空只保留Key参与签名,等号则不需要再加入签名。
String url =
Path +
"?" +
Key1 + "=" + Value1 +
"&" + Key2 + "=" + Value2 +
..."&" + KeyN + "=" + ValueN
-
-
计算签名。
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] keyBytes = secret.getBytes("UTF-8"); //App端调用则为App的App Secret;云端API调用则为云云对接的secret
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
String sign = new String(Base64.encodeBase64(hmacSha256.doFinal(stringToSign.getBytes("UTF-8")),"UTF-8")); -
传递签名。
将计算的签名结果放到Request的Header中,Key为x-ca-signature。
-
传递签名。 当签名校验失败时,API网关会将服务端的StringToSign放到HTTP Response的Header中返回到客户端,Key为X-Ca-Error-Message。只需要将本地计算的StringToSign与服务端返回的StringToSign进行对比即可找到问题。 如果服务端与客户端的StringToSign一致请检查用于签名计算的密钥是否正确。因为HTTP Header中无法表示换行,因此StringToSign中的换行符都被过滤掉了,对比时请忽略换行符。