Contents
API 接口访问签名算法文档
版本号 | 日期 | 修订要点 | 备注 |
---|---|---|---|
V2.2.1 | 2022/1/7 | 新建 |
一、目的
对接口访问需要进行校验签名,提供签名算法方便开发人员快速接入。
二、签名算法
签名的生成要素主要由 应用appKey
,应用appSecret
,随机数rand
,时间戳(单位秒)timestamp
按照一定的排列规则组成;生成的签名不能重复使用。
签名值生成过程
-
1.获取必要的
appKey
和appSecret
,由贵州天机信息科技有限公司提供 -
2.随机字符串 4-6 位的字符串
-
3.生成当前时间戳秒
-
4.按照一定规则进行排序得到一个 plain 字符串
- 排序方式:
appKey=%s&appSecret=%s&rand=%s×tamp=%s
- 排序方式:
-
5.最后使用
HmacSHA256
对plain
字符串进行消息摘要,使用appSecret
为消息摘要的密钥 -
6.在 http 请求头需要携带签名;
x-appKey
应用 appKey,x-signature
签名,x-timestamp
时间戳,x-rand
随机数。
三、算法参考
(一)JAVA
- 1.随机数生成
1 public static final String BASE = "abcdefghijklmnopqrstuvwxyz0123456789";
2
3 /**
4 * 随机生成4-6 位字符串
5 */
6 public static String randStr() {
7 StringBuilder sb = new StringBuilder();
8 int length = (int) (Math.random() * 3 + 4);
9 for (int i = 0; i < length; i++) {
10 int number = (int) (Math.random() *BASE.length());
11 sb.append(BASE.charAt(number));
12 }
13 return sb.toString();
14 }
- 2.时间戳 秒
1
2 /**
3 * 获取当前时间戳
4 *
5 * @return 时间戳字符串
6 */
7 public static String timestampStr() {
8 long second = Instant.now().getEpochSecond();
9 return String.valueOf(second);
10 }
- 3.签名
1public static String getSign(String appKey, String appSecret, String rand,String timestamp) throws Exception {
2
3
4 // 有随机数的签名
5 String raw = "appKey=%s&appSecret=%s&rand=%s×tamp=%s";
6 String plain = String.format(raw, appKey, appSecret,rand, timestamp);
7
8 SecretKeySpec secretKeySpec = new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
9 Mac mac = Mac.getInstance("HmacSHA256");
10 mac.init(secretKeySpec);
11 byte[] bytes = mac.doFinal(plain.getBytes());
12 return byte2HexString(bytes);
13 }
14
15 public static String byte2HexString(byte[] bytes) {
16 StringBuilder stringBuffer = new StringBuilder();
17 for (int i = 0; i < bytes.length; ++i) {
18 String temp = Integer.toHexString(bytes[i] & 255);
19 if (temp.length() == 1) {
20 stringBuffer.append("0");
21 }
22 stringBuffer.append(temp);
23 }
24 return stringBuffer.toString();
25 }
(二)Golang
- 1.随机数
1
2
3import (
4 mrand "math/rand"
5 "bytes"
6 "crypto/rand"
7 "math/big"
8)
9
10// BASE 随机字符串
11const BASE = "abcdefghijklmnopqrstuvwxyz0123456789"
12
13func RandStr() string {
14 var randStr string
15 b := bytes.NewBufferString(BASE)
16 length := 4 + mrand.Intn(3)
17 bigInt := big.NewInt(int64(b.Len()))
18 for i := 0; i < length; i++ {
19 randomInt, _ := rand.Int(rand.Reader, bigInt)
20 randStr += string(BASE[randomInt.Int64()])
21 }
22 return randStr
23}
- 2.签名
1package main
2
3import "fmt"
4import "crypto/hmac"
5import "crypto/sha256"
6import "encoding/hex"
7
8func CreateAccessSign(appKey, appSecret, rand,timestamp string) string {
9 // 有随机数的签名
10 plain := fmt.Sprintf("appKey=%s&appSecret=%s&rand=%s×tamp=%s", appKey, appSecret, rand, timestamp)
11 key := []byte(appSecret)
12 h := hmac.New(sha256.New, key)
13 h.Write([]byte(plain))
14 return hex.EncodeToString(h.Sum(nil))
15}
16
17
(三)Python
- 签名
1 import hmac, time, random
2 from hashlib import sha256
3
4
5 def hamc_sha256(key, plain):
6 sign = hmac.new(key, plain, sha256).hexdigest()
7 return sign
8
9
10 if __name__ == '__main__':
11 appKey = 'c7btj206n88j466jth10' #应用appKey
12 appSecret = 'c7btj706n88j4edermd0' #应用密钥
13 rand = random.randint(100000, 900000) # 6位随机数
14 timestamp = int(time.time())
15 raw = "appKey={}&appSecret={}&rand={}×tamp={}".format(appKey,appSecret, rand, timestamp)
16 sign = hamc_sha256(appSecret.encode(), raw.encode())
17 print(sign)
18
(四)JS
- 签名
1var appKey = '[接入方 appKey]';
2var appSecret = '[接入方 appSecret]';
3var timestamp = Math.round(new Date().getTime()/1000);//获取秒数时间戳
4var rand = Math.round(100000 + Math.random() * 900000);//6位随机数
5var magic = `appKey=${appKey}&appSecret=${appSecret}&rand=${rand}×tamp=${timestamp}`;
6var signature = CryptoJS.HmacSHA256(magic, appSecret).toString();
四、demo
以 Java 为例;提供一个访问接口的 demo。
- example
1
2 @Test
3 public void signTest() throws Exception {
4 //应用appKey
5 String appKey = "c7btj206n88j466jth10";
6 //应用密钥
7 String appSecret = "c7btj706n88j4edermd0";
8 //随机数
9 String rand = randStr();
10 //时间戳
11 String timestamp = timestampStr();
12 //生成签名
13 String sign = getSign(appKey, appSecret, rand, timestamp);
14 // 使用http访问接口
15 // 请求头携带 x-appKey,x-signature,x-timestamp,x-rand 参数
16 OkHttpClient client = new OkHttpClient();
17 String json = "";
18 String url = "http://192.168.1.22:9808/api/v1/xxx";
19 RequestBody body = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
20 Request request = new Request.Builder()
21 .addHeader("x-appKey", appKey)
22 .addHeader("x-signature", sign)
23 .addHeader("x-timestamp", timestamp)
24 .addHeader("x-rand", rand)
25 .url(url)
26 .post(body)
27 .build();
28 try (Response response = client.newCall(request).execute()) {
29 String bodyStr = response.body().string();
30 //打印响应结果
31 System.out.println(bodyStr);
32 }
33
34 }
1<!-- https://mvnrepository.com/artifact/xin.altitude.cms.common/ucode-cms-common -->
2<dependency>
3 <groupId>xin.altitude.cms.common</groupId>
4 <artifactId>ucode-cms-common</artifactId>
5 <version>1.2.9</version>
6</dependency>
7