鉴权与签名

概述

为保障接口调用的安全性与数据完整性,平台 API 采用 基于 HMAC-SHA256 的签名鉴权机制。 合作方在每次请求 API 时,需按照本文档规定的规则生成签名,并在 HTTP Header 中携带相关鉴权信息,否则请求将被拒绝。

该鉴权机制适用于所有需要身份认证的 API 接口。

鉴权参数说明

接入凭证

合作方在完成接入申请后,可登录平台官网创建 API 及子账户。

  • 系统将自动生成并分配对应的 API_KEY 与 API_SECRET,用于接口访问与签名计算;
  • API_PASSPHRASE 由合作方在创建 API 时自行设置,作为接口调用的安全校验口令;
  • 请合作方妥善保管上述凭证信息,避免泄露。如发生泄露,请及时重新生成相关密钥。

创建后将会拿到以下信息:

参数名说明
API_KEYAPI 访问身份令牌,用于标识调用方身份
API_SECRETAPI 私钥,用于生成签名(请妥善保管,不可泄露)
API_PASSPHRASEAPI 口令,用于增强安全校验
⚠️

安全提示

API_SECRET 仅用于本地签名计算,禁止在前端、日志或任何第三方环境中明文暴露。

请求头(HTTP Headers)

所有需要鉴权的请求,必须在 HTTP Header 中包含以下字段:

Header 名称是否必填说明
API_KEYAPI 访问身份令牌
ACCESS-SIGN请求签名
ACCESS-TIMESTAMP请求时间戳(毫秒)
API_PASSPHRASEAPI 口令

时间戳规则

  • ACCESS-TIMESTAMP 使用 Unix 时间戳(毫秒);
  • 示例:1766066126559(2025-12-18 21:56:09 622);
  • 平台将校验请求时间的有效性,请确保调用方服务器时间准确。

签名生成规则

签名算法

  • HMAC-SHA256;
  • 签名结果使用 Base64 编码。

待签名字符串(String To Sign)

签名字符串由以下字段按顺序拼接组成:

timestamp + HTTP_METHOD + request_path + query_string + request_body

拼接规则说明:

项目说明
timestamp请求时间戳(毫秒)
HTTP_METHOD请求方法,大写(GET / POST / PUT / DELETE)
request_pathURL 中的path部分(不含域名)
query_stringURL 查询参数(若存在,需加 ?)
request_body请求 Body 原始字符串(无 body 则为空字符串)

特别说明

请求路径

  • 仅包含路径部分
  • 示例:
/api/v1/order/place

Query String

若请求中存在查询参数,需按原始顺序拼接

示例:

?symbol=BTCUSDT&type=limit

Request Body

  • 使用 原始字符串;
  • JSON 请求体需保持字段顺序和格式一致;
  • 若无 body(如 GET 请求),使用空字符串。

代码实现示例

JS版本

const CryptoJS = require('crypto-js');

// 获取创建API时系统分配的API_KEY、API_SECRET,以及合作方自行设置的口令
const secret = pm.environment.get('API_SECRET');
const apiKey = pm.environment.get('API_KEY');
const apiPassphrase = pm.environment.get('API_PASSPHRASE');

// 生成时间戳 (毫秒)
const timestamp = Date.now().toString();

// 获取请求要素
const method = pm.request.method.toUpperCase();
// 获取路径部分
const path = pm.request.url.getPath();  
// 获取查询字符串
const query = pm.request.url.getQueryString(); 

console.log('接口URL请求参数:',query);

const rawBody = pm.request.body?.raw || '';

console.log('接口body请求参数:',rawBody);
// 构建待签名字符串
const stringToSign = timestamp + method + path + 
                    ( ? '?' + query : '') + 
                    rawBody;

console.log('待签名字符串:', stringToSign);

// 生成 HMAC SHA256 签名
const signature = CryptoJS.HmacSHA256(stringToSign, secret);
const accessSign = CryptoJS.enc.Base64.stringify(signature);

pm.request.headers.add({
    key: 'ACCESS-KEY',
    value: apiKey
});

// 设置header
pm.request.headers.add({
    key: 'ACCESS-SIGN',
    value: accessSign
});

//设置header
pm.request.headers.add({
    key: 'ACCESS-TIMESTAMP',
    value: timestamp
});


//设置header
pm.request.headers.add({
    key: 'ACCESS-PASSPHRASE',
    value: apiPassphrase
});



// 调试输出(可选)
console.log('ACCESS-SIGN:', accessSign);

console.log('请求头信息:',pm.request.headers);

JAVA版本

public static void main(String[] args) throws Exception {
        String secret = "5aed2291abf14a55c06bb14e311abf1f5458f8077209f6bbb2a8118d176d8d76";
        String timestamp = System.currentTimeMillis()+"";
        String method = "GET";
        String path = "/api/v3/time";
        String query = null;
        String body = null;


        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(timestamp)
                .append(method.toUpperCase())
                .append(path);

        if (query != null && !query.isEmpty()) {
            stringToSign.append("?").append(query);
        }

        if (body != null) {
            stringToSign.append(body);
        }

        String sign = ApiSignUtil.generateSignature(stringToSign.toString(), secret);
        System.out.println( sign);
}

public static String generateSignature(String body, String secret) {
    try {

        // HMAC-SHA256
        Mac mac = Mac.getInstance(HMAC_SHA256);
        SecretKeySpec secretKey =
                new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_SHA256);
        mac.init(secretKey);

        byte[] rawHmac = mac.doFinal(
                body.getBytes(StandardCharsets.UTF_8)
        );

        // Base64 编码
        return Base64.getEncoder().encodeToString(rawHmac);

    } catch (Exception e) {
        throw new RuntimeException("Failed to generate API signature", e);
    }
}