签名计算使用指引

签名机制

为保证 HTTP/HTTPS 服务的安全使用,在服务配置中可选择开启签名计算,在调用 API 时全局服务会对开启签名的服务进行签名计算,并将签名放到请求header中。本文介绍计算签名的方法和示例。

步骤一:构造规范化请求字符串

1、CanonicalizedHeaderString:

(1)header参数范围:包括header中以“x-dmpaas”开头的系统参数、header自定义参数,不包括header参数中的x-dmpaas-signature参数。

(2)header参数排序和拼接:

按照参数字符串字典升序对header参数排序,多个header之间用&连接。

使用等号(=)连接编码后的header参数和编码后的header参数值,编码方式参考附录。

示例:

Headers:

自定义参数

test-header1=test-header-value1

test-header2=test-header-value2

系统参数:

x-dmpaas-accesskey=testkey

x-dmpaas-beebot-chat-id=beebot-chat-id-value

x-dmpaas-signature-nonce=d990cdec-3b2c-4235-a836-704f3a4dfa18

x-dmpaas-timestamp=2022-12-08T14:11:16Z

结果:

CanonicalizedHeaderString字符串是test-header1=test-header-value1&test-header2=test-header-value2&x-dmpaas-accesskey=testkey&x-dmpaas-beebot-chat-id=beebot-chat-id-value&x-dmpaas-signature-nonce=d990cdec-3b2c-4235-a836-704f3a4dfa18&x-dmpaas-timestamp=2022-12-08T14%3A11%3A16Z

2、CanonicalizedQueryString:

(1)query参数范围:全局服务页面上所有query参数、URL连接串提前预置的query参数。

(2)query参数排序和拼接:

使用等号(=)连接编码后的query参数和编码后的query参数值,编码方式参考附录。

按照参数字符串字典升序对query参数排序,多个query之间用&连接。

示例:

Querys :

key1=value1

key2=value2

CanonicalizedQueryString字符串是key1=value1&key2=value2

3、CanonicalizedBodyString:请求的body 字符串,如果没有body,就用空字符串("");

步骤二:构造签名字符串

我们以 Java 为例,该字符串构造规则如下:

String stringToSign =

HTTPMethod + "&" +

encodeURIComponent("/") + "&" +

encodeURIComponent(CanonicalizedHeaderString) + "&" +

encodeURIComponent(CanonicalizedQueryString) + "&" +

encodeURIComponent(CanonicalizedBodyString)

备注:

HTTPMethod:发送请求的 HTTP 方法,例如 POST

encodeURIComponent编码方法是指:使用 UTF-8 字符集按照RFC3986规则(https://www.rfc-editor.org/rfc/rfc3986?spm=a2c4g.11186623.0.0.549927b5NRn8tS#page-28)编码请求参数和参数值进行URLEncode,编码具体规则请参看“附录:参数编码方式”。

步骤三:计算签名

在全局服务配置中可查到AccessKey匹配的AccessToken,作为加密的密钥,使用 HMAC-SHA1 的签名算法,计算待签名字符串StringToSign的签名。以 Java 为例,计算方法如下:

String signature = Base64(HMAC_SHA1(accessToken + "&", stringToSign))

现在您得到了公共参数 Signature 的签名值 signature。然后和请求header中x-dmpaas-signature的值进行对比。

签名示例

模拟请求配置

HTTPMethod: POST;

Headers:

自定义参数

test-header1=test-header-value1

test-header2=test-header-value2

系统参数:

x-dmpaas-accesskey=testkey

x-dmpaas-beebot-chat-id=beebot-chat-id-value

x-dmpaas-signature-nonce=d990cdec-3b2c-4235-a836-704f3a4dfa18

x-dmpaas-timestamp=2022-12-08T14:11:16Z

Querys:

key1=value1

key2=value2

Body:

{"test-body-key1":"test-body-value1","test-body-key2":"test-body-value2"}

假设您获得了AccessKey=testkey 以及 AccessToken=testtoken,签名流程如下:

步骤一:构造规范化请求字符串

CanonicalizedHeaderString:test-header1=test-header-value1&test-header2=test-header-value2&x-dmpaas-accesskey=testkey&x-dmpaas-beebot-chat-id=beebot-chat-id-value&x-dmpaas-signature-nonce=d990cdec-3b2c-4235-a836-704f3a4dfa18&x-dmpaas-timestamp=2022-12-08T14%3A11%3A16Z

CanonicalizedQueryString:key1=value1&key2=value2

CanonicalizedBodyString:{"test-body-key1":"test-body-value1","test-body-key2":"test-body-value2"}

步骤二:构造待签名字符串stringToSign

POST&%2F&test-header1%3Dtest-header-value1%26test-header2%3Dtest-header-value2%26x-dmpaas-accesskey%3Dtestkey%26x-dmpaas-beebot-chat-id%3Dbeebot-chat-id-value%26x-dmpaas-signature-nonce%3Dd990cdec-3b2c-4235-a836-704f3a4dfa18%26x-dmpaas-timestamp%3D2022-12-08T14%253A11%253A16Z&key1%3Dvalue1%26key2%3Dvalue2&%7B%22test-body-key1%22%3A%22test-body-value1%22%2C%22test-body-key2%22%3A%22test-body-value2%22%7D

步骤三:计算签名

计算签名值。例如 AccessToken=testtoken,用于计算的 Key 为testtoken&(注意:加上后缀&)。计算得到的签名值为jpvM83XOLhJ1lHTQR2boROe****=。本示例使用的是 Java Base64 编码方法。

String Signature = Base64(HMAC_SHA1(AccessSecret + "&",stringToSign))

最后您可以比较请求header中的x-dmpaas-signature的值,来进行签名校验。

附录

参数编码方式

在全局服务-HTTP/HTTPS服务调用中,我们需要对请求参数和请求值,使用 UTF-8 字符集按照RFC3986规则进行编码。具体编码规则如下:

字符 A~Z、a~z、0~9 以及字符-、_、.、~不编码。

对其他 ASCII 码字符进行编码。编码格式为%加上16进制的 ASCII 码。例如半角双引号(")将被编码为 %22。

非 ASCII 码通过 UTF-8 编码。

空格编码成%20,而不是加号(+)。

以Java为例:

java.net.URLEncoder.encode(str, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~")

为方便表述,我们将此步骤的编码方法,命名为 encodeURIComponent。