功能介绍
应用鉴权是第三方应用程序/服务 调用云鲸AIoT开发者平台服务的一种签名鉴权机制。本文主要介绍如何进行应用鉴权。
前提条件
您已完成创建应用 的步骤。
逻辑图
鉴权加密算法
- 对请求参数进行排序并加密
// 使用 TreeMap 对请求参数 自然排序,并转为 Json 字符串,然后使用 SHA256 加密并转为16进制字符串。
// 伪代码↓
HexEncode(Hash.SHA256(payloadJson))
目前支持的参数方式:
- HTTP GET 请求:将请求参数以 Key 、Value 形式放入Map中。value 需为字符串类型。
- HTTP POST 请求,请求类型为 application/Json : 支持JSON对象传递,将JSON对象中的第一层级的 Key 、Value 放入Map中,如Value 仍为 JSON对象,也同样需要进行自然排序。其他类型value 需为字符串类型。
- HTTP POST 请求,请求类型为 multipart/form-data : 将普通参数以 Key 、Value 形式放入Map中,文件参数不参与校验过程。如Value 仍为 JSON对象,也同样需要进行自然排序。其他类型value 需为字符串类型。
- 拼接待签名字符串
//按照如下格式进行拼接待签名字符串:
StringToSign = Algorithm + ‘\n’ + date + ‘\n’ + HashedRequestPayload
字段说明:
字段名称 | 解释 | |
---|---|---|
1 | Algorithm | 签名算法,固定为 HMAC-SHA256 |
2 | date | UTC 标准时间的日期,取值需要和请求参数中 timestamp 换算的 UTC 标准时间日期一致 |
3 | HashedRequestPayload | 第一步所得规范请求串的哈希值 |
- 根据以上规则,得到待签名字符串如下:
HMAC-SHA256
2021-06-23 01:11:12
3b6099ce6240a6cfa8a4f77a2d3e5cd723b6fa9d2d43031b340b9362eb3ed434
- 计算签名
计算签名的伪代码如下:
String signature = HexEncode(HMAC_SHA256(Assess key Secret, StringToSign))
signature = signature.toLowerCase()
- 拼接Authorization
按如下格式拼接 Authorization:
Authorization = Algorithm + ‘ ‘ + ‘Signature=’ + Signature ‘ ‘+ ‘AccessKey=’+ AK + ‘ ‘ + ‘Timestamp=’ + timestamp
鉴权加密算法代码示例
JAVA版本
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class ApiAuthorizationDemo{
private final static Charset UTF8 = StandardCharsets.UTF_8;
public static byte[] hmac256(byte[] key, String msg) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
return mac.doFinal(msg.getBytes(UTF8));
}
public static String sha256Hex(String s) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] d = md.digest(s.getBytes(UTF8));
return DatatypeConverter.printHexBinary(d).toLowerCase();
}
public static void main(String[] args) throws Exception {
String algorithm = "HMAC-SHA256";
String accessKey = "915d957d05ff44f3aeb12413e2247e5cdb5e";
String accessKeySecret = "c7531c2357e2200bb7eee3fe190f138a0febcbec791241417aceac0418f8c662657b97e5fa87b5b4b9bafb";
//组装参数,此处以设备注册为例子
final TreeMap<String, Object> treeMap = Maps.newTreeMap();
treeMap.put("productId","pJabWNSCCU");
final Long timestamp = System.currentTimeMillis();
//参数转为JSON,并进行加密
final JSONObject jsonObject = JSONUtil.parseObj(treeMap,JSONConfig.create().setOrder(true));
final String jsonStr = jsonObject.toString();
final String hashedRequestPayload = sha256Hex(jsonStr);
//拼接待签名字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" );
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String date = sdf.format(new Date(Long.valueOf(timestamp)));
String stringToSign = algorithm + "\n" + date + "\n" + hashedRequestPayload;
//计算签名
final String signature = DatatypeConverter.printHexBinary(hmac256(accessKeySecret.getBytes(UTF8), stringToSign)).toLowerCase();
//拼接Authorization
String authorization = algorithm + " " + "Signature="+signature + " " + "AccessKey="+ accessKey + " " + "Timestamp=" + timestamp ;
}
}
Node JS版本
/* eslint-disable no-restricted-syntax */
import * as crypto from 'crypto';
const {
createHash,
createHmac,
} = crypto;
const algorithm = 'HMAC-SHA256';
type GetAuthorizationOptions = {
payload: {},
accessKey: string,
accessSecret: string,
};
// 自然排序
function sortObj(obj) {
const newObj = {};
Object.assign(newObj, obj);
const keys = Object.keys(newObj); // Cannot convert undefined or null to object
keys.sort();
const sorted = {};
for (const k of keys) {
sorted[k] = obj[k];
}
return sorted;
}
function hashSha256(content: string): string {
return createHash('sha256').update(content).digest('hex');
}
function hmacSha256(content: string, secret: string): string {
return createHmac('sha256', secret).update(content).digest('hex');
}
function getFull(v) {
return v < 10 ? `0${v}` : v;
}
function getUTC(date: Date): string {
const y = date.getUTCFullYear();
const m = getFull(date.getUTCMonth() + 1);
const d = getFull(date.getUTCDate());
const h = getFull(date.getUTCHours());
const M = getFull(date.getUTCMinutes());
const s = getFull(date.getUTCSeconds());
return `${y}-${m}-${d} ${h}:${M}:${s}`;
}
function getAuthorization(options: GetAuthorizationOptions): string {
const { payload, accessKey, accessSecret } = options;
const now = new Date();
// 1:对请求参数进行排序并加密
const sha256Result = hashSha256(JSON.stringify(sortObj(payload)));
// 2: 拼接待签名字符串
const stringToSign = `${algorithm}
${getUTC(now)}
${sha256Result}`;
// 3:计算签名
const hmacSha256Result = hmacSha256(stringToSign, accessSecret);
// 4:拼接 Authorization
const Authorization = `${algorithm} Signature=${hmacSha256Result} AccessKey=${accessKey} Timestamp=${now.valueOf()}`;
return Authorization;
}
// 调用方式
// getAuthorization({
// payload: {},
// accessKey: 'xxx',
// accessSecret: 'xxx',
// });
export default getAuthorization;
Python版本
import hashlib
import hmac
import json
from datetime import datetime
from collections import OrderedDict
# HMAC-SHA256 签名函数
def hmac_sha256(key: bytes, msg: str) -> bytes:
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
# SHA-256 哈希函数
def sha256_hex(s: str) -> str:
return hashlib.sha256(s.encode('utf-8')).hexdigest().lower()
# 生成授权头
def generate_authorization(algorithm, access_key, access_key_secret, params, timestamp):
# 1. 参数排序(使用 OrderedDict)
ordered_params = OrderedDict(sorted(params.items()))
# 2. 转换为 JSON 字符串
json_str = json.dumps(ordered_params, separators=(',', ':'), ensure_ascii=False)
# 3. 计算请求体的哈希值
hashed_request_payload = sha256_hex(json_str)
# 4. 格式化时间戳
date = datetime.utcfromtimestamp(timestamp / 1000).strftime('%Y-%m-%d %H:%M:%S')
# 5. 拼接待签名字符串
string_to_sign = f"{algorithm}\n{date}\n{hashed_request_payload}"
# 6. 计算签名
signature = hmac_sha256(access_key_secret.encode('utf-8'), string_to_sign)
signature_hex = signature.hex().lower()
# 7. 生成 Authorization 字符串
authorization = f"{algorithm} Signature={signature_hex} AccessKey={access_key} Timestamp={timestamp}"
return authorization
if __name__ == "__main__":
algorithm = "HMAC-SHA256"
access_key = "wSO4H0oBiLmtZmq32QpV"
secret_key = "4ac8041f96ce47e2bd1d3228fe049e93"
timestamp = 1727333198611
params = {
"productId": "hEA7OEshlx",
"query": "全军出击",
"custom": "全军出击",
"logId": "test",
"deviceId": "9090ce544bdf4e7ea1f5f4193b2190dc",
"device": {
"ak": "tIFs1d2wes",
"fc": "z4863s",
"pk": "gc0s8bug"
},
"nluInfos": "全军出击"
}
# 生成 Authorization
authorization = generate_authorization(algorithm, access_key, secret_key, params, timestamp)
print(authorization)
统一请求路径
创建时间:2023-03-28 21:40
最后编辑:admin 更新时间:2025-02-28 15:26
最后编辑:admin 更新时间:2025-02-28 15:26