# API签名算法及工具

    # 签名计算工具

    某些 API 为了保证安全性,需要通过 Ocean 验证客户端的身份,Ocean 通过 appKey 及 API 签名验证客户端身份,防止请求在网络传输过程中被篡改。

    /openapi/param2/1

    域名可改;中间 /openapi/param2/1 为固定;后段为 path,格式 namespace/apiName/appKey

    填入 API 请求的参数,格式为 key1=value1&key2=value2... 如果没有则不填。注意此处填写的参数不要进行 encode,最终的 URL 才要 encode。

    填入与 urlPath 中 appKey 对应的 appSecret。

    # 签名算法及示例

    调用 URL 中必须带入签名信息,作为接入方将会得到 appKey 和 appSecret,签名结果以 _aop_signature=xxxx 的参数形式发送到服务端。

    如:

    http://open.daqihui.com/openapi/http/1/system/currentTime/1688?b=1&a=2&_aop_signature=2F1E96587451DE0E171978F4AAE1A90FF9B2F94B

    API 签名,顾名思义签名结果跟 API 有关,主要跟 urlPath(包含 API 基本信息)以及请求参数(API 入参)有关,具体算法如下:

    1. 构造 urlPath:urlPath 是 URL 中的一部分,从协议开始截取,到 ? 为止,包含了协议、namespace、apiName 和 apiVersion,如 urlPath=http/1/system/currentTime/1688
    2. 拼装参数:首先将所有参数按照 key+value 拼装得到一个字符串数组(如 [b1,a2]),然后对数组进行排序([a2,b1]),最后将排序后的数组合并为字符串(a2b1)。
    3. 合并:把前两步的字符串拼接(http/1/system/currentTime/1688a2b1)。
    4. 执行 hmac_sha1 算法Signature = uppercase(hex(hmac_sha1(concatString, secretKey)))。假设 secretKey=test123,那么得到的签名为 2F1E96587451DE0E171978F4AAE1A90FF9B2F94B
      • a) concatString 为合并后的字符串;
      • b) secretKey 为签名密钥,与 urlPath 中的 appKey 对应;
      • c) hmac_sha1 为通用的 hmac_sha1 算法,各编程语言一般都对应类库;
      • d) hex 为转为十六进制;
      • e) uppercase 为转为大写字符。

    # 关键签名算法实现 Java 演示

    参考授权示例代码(Java)中的 CommonUtil 类。

    # 关键签名算法实现 PHP 演示

    <?php 
        $url = 'http://open.daqihui.com/openapi';
        $appKey = '1222';
        $appSecret = '232323';
        $apiInfo = 'param2/1/system/currentTime/' . $appKey;
        
        $code_arr = array(
            'param1' => 'xx',
            'param2' => 'xx'
        );
        $aliParams = array();
        foreach ($code_arr as $key => $val) {
            $aliParams[] = $key . $val;
        }
        sort($aliParams);
        $sign_str = join('', $aliParams);
        $sign_str = $apiInfo . $sign_str;
        $code_sign = strtoupper(bin2hex(hash_hmac("sha1", $sign_str, $appSecret, true)));
    ?>
    

    # 关键签名算法实现 C# 演示

    // urlPath: 基础url部分,格式为 protocol/apiVersion/namespace/apiName/appKey
    // paramDic: 请求参数,即 queryString + request body 中的所有参数
    private string sign(string urlPath, Dictionary<string, string> paramDic)
    {
        byte[] signatureKey = Encoding.UTF8.GetBytes("YOURSIGNATRUEKEY");
        List<string> list = new List<string>();
        foreach (KeyValuePair<string, string> kv in paramDic)
        {
            list.Add(kv.Key + kv.Value);
        }
        list.Sort();
        string tmp = urlPath;
        foreach (string kvstr in list)
        {
            tmp = tmp + kvstr;
        }
        HMACSHA1 hmacsha1 = new HMACSHA1(signatureKey);
        hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(tmp));
        byte[] hash = hmacsha1.Hash;
        return BitConverter.ToString(hash).Replace("-", string.Empty).ToUpper();
    }
    

    # 关键签名算法实现 Objective-C 演示

    + (NSString*)stringWithHexBytes:(NSData *)objData {
        static const char hexdigits[] = "0123456789ABCDEF";
        const size_t numBytes = [objData length];
        const unsigned char* bytes = [objData bytes];
        char *strbuf = (char *)malloc(numBytes * 2 + 1);
        char *hex = strbuf;
        NSString *hexBytes = nil;
        for (int i = 0; i<numBytes; ++i) { 
            const unsigned char c = *bytes++;
            *hex++ = hexdigits[(c >> 4) & 0xF];
            *hex++ = hexdigits[(c ) & 0xF];
        }
        *hex = 0;
        hexBytes = [NSString stringWithUTF8String:strbuf];
        free(strbuf);
        return hexBytes;
    }
    
    + (NSString *)hmacSha1ToHexStr:(NSString *)strData key:(const char *)cKey
    {
        const char *cData = [strData cStringUsingEncoding:NSUTF8StringEncoding];
        unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
        CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
        NSData *hmac = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
        NSString *hash = [SecurityUtil stringWithHexBytes:hmac];
        [hmac release];
        return [hash autorelease];
    }
    
    + (NSString *)signature:(NSString *)pathUrl params:(NSDictionary *)paramMap key:(const char *)cKey
    {
        NSMutableArray *params = [[NSMutableArray alloc] init];
        NSRange range = [pathUrl rangeOfString:@"?"];
        NSString *baseUrl;
        if(range.length > 0) {
            baseUrl = [pathUrl substringToIndex:range.location];
            // ... 解析 query 到 params
        } else {
            baseUrl = pathUrl;
        }
        for (NSString *key in [paramMap allKeys]) {
            NSMutableString *tmp = [[NSMutableString alloc] initWithString:key];
            [tmp appendString:[paramMap valueForKey:key] ?: @""];
            [params addObject:[tmp autorelease]];
        }
        [params sortUsingSelector:@selector(compare:)];
        // CCHmac 计算 ...
        return hash;
    }
    
    最后更新于: 2026/2/26 15:32:57