# 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 入参)有关,具体算法如下:
- 构造 urlPath:urlPath 是 URL 中的一部分,从协议开始截取,到
?为止,包含了协议、namespace、apiName 和 apiVersion,如urlPath=http/1/system/currentTime/1688。 - 拼装参数:首先将所有参数按照
key+value拼装得到一个字符串数组(如[b1,a2]),然后对数组进行排序([a2,b1]),最后将排序后的数组合并为字符串(a2b1)。 - 合并:把前两步的字符串拼接(
http/1/system/currentTime/1688a2b1)。 - 执行 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为转为大写字符。
- a)
# 关键签名算法实现 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;
}
← SDK下载
