You need to enable JavaScript to run this app.
导航
公共请求头说明
最近更新时间:2023.02.14 18:01:31首次发布时间:2022.04.13 17:53:21

本章介绍HTTP调用方式,适用基于API URL发起HTTP/HTTPS POST请求的用户。

HTTP请求头部

参数说明示例是否必传
Tenant-Id火山引擎申请的账号id/租户id(tenant_id),数字类型,如2100021,header传入。2100021
Tenant-Ts当前时间戳,单位秒。150345676
Tenant-Nonce随机字符串,可以使用当前时间戳。ab1234fs34dbkdsu
Tenant-Signature旧版鉴权签名,如果使用SDK的话无需关注。
1. 火山引擎侧提供token。(token:分配给客户的secret-key,由字节侧提供,与火山引擎生成的AccessKey Secret不同,用于鉴权加密的密钥,每个租户独立分配,每个租户下所有项目的token相同)。
2. 获取当前时间戳(Tenant-Ts),并转成字符串。
3. 生成随机字符串(Tenant-Nonce)。
4. 按照token、body(请求体,需要序列化成字节流)、Tenant-Id、Tenant-Ts、Tenant-Nonce顺序,将各字段拼接在一起。5. 使用sha-256对拼接后的字段进行hash。
6. 将得到的hash结果按照16进制编码得到字符串(大小写不敏感),该字符串即为签名Tenant-Signature。
7a73b4193a46727
af2b7355757fc2e8
47c5659107d7a806
bdecd6e46cf9644ab
Request-Id请求id,由客户方自己给出,只要保证每次请求的request-id唯一即可,不要求具体格式,但建议不要太长。84kduxkls74lcdj73jdu3
Content-Type请求体序列化方式,支持“application/x-protobuf”和“application/json”,具体使用哪种参考每个接口的说明。application/json
Accept返回体序列化方式,如果该header不存在,则使用“Content-Type”的序列化方式。application/json

签名计算流程

alt

不同语言签名校验函数示例

Go

import (
   "crypto/sha256"
   "encoding/json"
   "fmt"
   "github.com/spf13/cast"
   "time"
)

func main() {
   token := "xxx"                                      // 由字节侧提供.
   tenantId := "xxx"                                   // 租户id
   tenantTs := cast.ToString(time.Now().Unix())        // 当前时间戳
   tenantNonce := cast.ToString(time.Now().UnixNano()) // 使用纳秒时间戳作为随机字符串
   httpBody, _ := json.Marshal(map[string]interface{}{ // 示例用http body.真实请求请替换成实际使用的body.
      "user": map[string]string{
         "uid": "123",
      },
   })
   sign := calSignature(token, tenantId, tenantTs, tenantNonce, httpBody)
   fmt.Println(fmt.Sprintf("sign: %s", sign))
}

func calSignature(token, tenantId, tenantTs, tenantNonce string, httpBody []byte) string {
   //按照token,body,tenantId,tenantTs,tenantNonce顺序将各字段拼接在一起
   shaHash := sha256.New()
   shaHash.Write([]byte(token))
   shaHash.Write(httpBody)
   shaHash.Write([]byte(tenantId))
   shaHash.Write([]byte(tenantTs))
   shaHash.Write([]byte(tenantNonce))
   //将sha256转成16进制字符串
   signature := fmt.Sprintf("%x", shaHash.Sum(nil))
   return signature
}

Java

import com.alibaba.fastjson2.JSON;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.UUID;

public class Main {
    public static void main(String[] args) {
        String token = "xxx"; // 由字节侧提供.
        String tenantId = "xxx"; // 租户id
        String tenantTs = Integer.toString((int) (System.currentTimeMillis() / 1000)); // 当前时间戳
        String tenantNonce = UUID.randomUUID().toString().substring(0, 8); // 随机字符串
        byte[] httpBody = JSON.toJSONBytes(new HashMap<>() {{ // 示例用http body.真实请求请替换成实际使用的body.
            put("user", new HashMap<>() {{
                put("uid", "123");
            }});
        }});
        String sign = calSignature(token, tenantId, tenantTs, tenantNonce, httpBody);
        System.out.printf("sign: %s", sign);
    }

    //根据token、tenant_id、tenantTs、tenantNonce、httpBody计算signature
    public static String calSignature(String token, String tenant_id, String tenantTs, String tenantNonce, byte[] httpBody) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            // 按照token、httpBody、tenant_id、ts、nonce的顺序拼接
            // 本身为字符串的字段,需要使用utf-8方式编码成字节数组
            // httpBody本身为bytes类型,因此无需编码
            digest.update(token.getBytes(StandardCharsets.UTF_8));
            digest.update(httpBody);
            digest.update(tenant_id.getBytes(StandardCharsets.UTF_8));
            digest.update(tenantTs.getBytes(StandardCharsets.UTF_8));
            digest.update(tenantNonce.getBytes(StandardCharsets.UTF_8));
            // 将得到sha256使用16进制字符串表示
            return bytes2Hex(digest.digest());
        } catch (NoSuchAlgorithmException ignored) {
            return "";
        }
    }

    public static String bytes2Hex(byte[] bts) {
        StringBuilder des = new StringBuilder();
        String hex;
        for (byte bt : bts) {
            // 剔除负数强转成int后补上的"ffffff"
            hex = (Integer.toHexString(bt & 0xff));
            // 始终用两个16进制代表一个byte,不够的在前面补“0”
            if (hex.length() == 1) {
                des.append("0");
            }
            des.append(hex);
        }
        return des.toString();
    }
}

Python

import hashlib
import json
import string
import time
import random


def cal_signature(token, tenant_id, tenant_ts, tenant_nonce, http_body):
    sha256 = hashlib.sha256()
    sha256.update(token.encode('utf-8'))
    sha256.update(http_body.encode('utf-8'))
    sha256.update(tenant_id.encode('utf-8'))
    sha256.update(tenant_ts.encode('utf-8'))
    sha256.update(tenant_nonce.encode('utf-8'))
    return sha256.hexdigest()


if __name__ == '__main__':
    token = 'xxx' # 由字节侧提供.
    tenant_id = 'xxx' # 租户id
    tenant_ts = str(int(time.time())) # 当前时间戳
    tenant_nonce = ''.join(random.sample(string.ascii_letters + string.digits, 8)) # 随机字符串
    http_body = json.dumps({ # 示例用http body.真实请求请替换成实际使用的body.
        "user": {
            "uid": "123"
        }
    })
    sign = cal_signature(token, tenant_id, tenant_ts, tenant_nonce, http_body)
    print('sign: ', sign)