阿里云物联网平台调用云端api时,签名的js实现过程

物联网平台提供云端管理产品、设备、分组、Topic、规则、设备影子等API接口,和从云端发布消息的API接口。使用云端SDK,向API的服务端地址发送HTTPS/HTTP GET或POST请求,并按照API接口说明,在请求中加入相应请求参数来调用API。物联网平台根据请求的处理情况,返回处理结果。

api接口列表参考文档:

https://help.aliyun.com/document_detail/69893.html

公共参数说明参考文档:

https://help.aliyun.com/document_detail/30561.html

签名机制参考文档:

https://help.aliyun.com/document_detail/30563.html

签名机制文档中提供一个java版的签名demo,未提供其他语言的,下面是我实现的js版签名过程。


const crypto = require('crypto');
const urlencode = require('urlencode');
const moment = require("moment");

function timestamp() {
    var date = new Date();
    var time = moment(date).utcOffset(0).format("YYYY-MM-DDTHH.mm.ss");
    time += 'Z';
    console.log("date===" + date);
    console.log("time===" + time);
    // 删除掉毫秒部分
    return time;
}

function encode(str) {
    var result = urlencode(str, "utf8");

    return result.replace(/!/g, '%21')
        .replace(/'/g, '%27')
        .replace(/\(/g, '%28')
        .replace(/\)/g, '%29')
        .replace(/\*/g, '%2A');
}

function replaceRepeatList(target, key, repeat) {
    for (var i = 0; i < repeat.length; i++) {
        var item = repeat[i];

        if (item && typeof item === 'object') {
            const keys = Object.keys(item);
            for (var j = 0; j < keys.length; j++) {
                target[`${key}.${i + 1}.${keys[j]}`] = item[keys[j]];
            }
        } else {
            target[`${key}.${i + 1}`] = item;
        }
    }
}

function flatParams(params) {
    var target = {};
    var keys = Object.keys(params);
    for (let i = 0; i < keys.length; i++) {
        var key = keys[i];
        var value = params[key];
        if (Array.isArray(value)) {
            replaceRepeatList(target, key, value);
        } else {
            target[key] = value;
        }
    }
    return target;
}

function normalize(params) {
    var list = [];
    var flated = flatParams(params);
    var keys = Object.keys(flated).sort();
    for (let i = 0; i < keys.length; i++) {
        var key = keys[i];
        var value = flated[key];
        list.push([encode(key), encode(value)]);
    }
    return list;
}

function canonicalize(normalized) {
    var fields = [];
    for (var i = 0; i < normalized.length; i++) {
        var [key, value] = normalized[i];
        fields.push(key + '=' + value);
    }
    return fields.join('&');
}

var AccessKeyId = "";
var accessSecret = "";
/*
var str = "POST&%2F&AccessKeyId%3D" + AccessKeyId
    + "%26Action%3DQueryDevice%26Format%3DJSON%26ProductKey%3Da1tDKl1PBkl%26RegionId%3Dcn-shanghai%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D86439216304009%26SignatureVersion%3D1.0%26Timestamp%3D2021-12-28T06%253A37%253A48Z%26Version%3D2018-01-20";;

*/
var str = "";
var httpmethod = "POST";
var params = {};
params.Format = "JSON";
params.Version = "2018-01-20";
params.AccessKeyId = AccessKeyId;
params.SignatureMethod = "HMAC-SHA1";
//params.Timestamp = timestamp();
params.Timestamp = '2021-12-28T06:37:48Z';
params.SignatureVersion = "1.0";
params.SignatureNonce = "86439216304009";
params.Action = "QueryDevice";
params.ProductKey = "a1tDKl1PBkl";
params.RegionId = "cn-shanghai";

var normalized = normalize(params);
console.log("normalized===" + normalized);

var canonicalized = canonicalize(normalized);

console.log("canonicalized===" + canonicalized);

str = httpmethod + "&" + encode("/") + "&" + encode(canonicalized);

console.log("str===" + str);

var key = accessSecret + "&";
const signature = Buffer.from(crypto.createHmac('sha1', key).update(str).digest()).toString('base64');

console.log("signature==="+signature);
console.log("最终signature===" + encode(signature));
上一篇:nginx open files limits 导致大量错误信息


下一篇:iot云产品流转测试