签名机制

平台会对每个接口访问请求的发送者进行身份验证,在请求中需要包含签名信息。

1 签名方法

首先,需要在管理平台 设置/授权管理 页面创建您的appKeyappSecret,其中appKey用于标识访问者身份;appSecret 是用于加密签名字符串和服务器端验证签名字符串的密钥,须严格保密。如图:签名生成

签名参数包括:

参数名 参数值 参数位置 备注
x-auth-accesskey appKey 请求头 为appKey
x-auth-traceid 请求唯一ID 请求头 5分钟内不重复
x-auth-ts 13位时间戳 请求头 请求的时间戳
x-auth-body body 一般POST、PUT、DELETE等请求时有body,如果不为空,则参与签名
查询字符串 query/param 即?key1=value1&key2=value2中的key1,key2

超时排错提示

其中x-auth-ts是调用方当前时间戳,只有当调用方和服务器时间相差较大,才应该查阅接口获取服务器时间戳

以下是签名方法:

  1. 按照签名参数名字典升序排列非空请求参数,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串signText;
  2. 对signText进行HMAC_MD5运算,appSecret作为加密密钥,并将得到的字符串转换为大写,得到x-auth-sign值,作为请求头的一项值。

2 签名示例

  • postman请求签名示例
(function() {
  var signContent = [];

  var accessKey = pm.environment.get("accessKey");
  var secretKey = pm.environment.get("secretKey");
  var timestamp = new Date().valueOf();
  var traceId = "traceId-" + timestamp;

  signContent.push("x-auth-accesskey=" + accessKey);
  signContent.push("x-auth-traceid=" + traceId);
  signContent.push("x-auth-ts=" + timestamp);

  var index = request.url.indexOf("?");
  if (index != -1) {
    var str = request.url.substr(index + 1);
    if (str !== "") {
      var params = str.split("&");
      signContent = signContent.concat(params);
    }
  }
  if (Object.keys(request.data).length > 0)
    signContent.push("x-auth-body=" + request.data);

  // 排序后拼接,签名原始字符串
  var signText = signContent.sort().join("&");
  var sign = CryptoJS.HmacMD5(signText, secretKey)
    .toString()
    .toUpperCase();
  console.log(sign, signText);
    
  pm.environment.set('x-auth-accesskey', accessKey);
  pm.environment.set('x-auth-ts', timestamp);
  pm.environment.set('x-auth-traceid', traceId);
  pm.environment.set('x-auth-sign', sign);
  
  console.log(request);
})();
  • Java签名示例
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * seewo iot签名示例
 */
public class SignDemo {

    private static final String accessKey = "accessKey";
    private static final String secret = "secret";

    private static final String HTTP_REQ_BODY = "";

    public static void main(String[] args) {
        TreeMap<String, String> params = new TreeMap<>();
        params.put("x-auth-ts", String.valueOf(System.currentTimeMillis()));
        params.put("x-auth-traceid", "traceId-123");
        params.put("x-auth-accesskey", accessKey);

        if (StringUtils.isNotEmpty(HTTP_REQ_BODY)) {
            params.put("x-auth-body", HTTP_REQ_BODY);
        }

        String sign = createSign(params, secret);
        System.err.println(sign);
    }

    private static String createSign(Map<String, String> params, String accessSecret) {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuilder temp = new StringBuilder();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = String.valueOf(value);
            }
            temp.append(valueString);
        }
        return encryptHMAC(temp.toString(), accessSecret)
                .toUpperCase(); // 转大写
    }

    private static String encryptHMAC(@NotNull String data, @NotNull String key) {
        try {
            SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "hmacMD5");
            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
            mac.init(secretKey);
            byte[] digest = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return new HexBinaryAdapter().marshal(digest);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
}