Contents

API 接口访问签名算法文档

版本号 日期 修订要点 备注
V2.2.1 2022/1/7 新建

一、目的

对接口访问需要进行校验签名,提供签名算法方便开发人员快速接入。

二、签名算法

签名的生成要素主要由 应用appKey,应用appSecret,随机数rand,时间戳(单位秒)timestamp按照一定的排列规则组成;生成的签名不能重复使用。

签名值生成过程

  • 1.获取必要的appKeyappSecret,由贵州天机信息科技有限公司提供

  • 2.随机字符串 4-6 位的字符串

  • 3.生成当前时间戳秒

  • 4.按照一定规则进行排序得到一个 plain 字符串

    • 排序方式:appKey=%s&appSecret=%s&rand=%s&timestamp=%s
  • 5.最后使用HmacSHA256plain字符串进行消息摘要,使用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&timestamp=%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&timestamp=%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={}&timestamp={}".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}&timestamp=${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