Qt6.5 OneNET Studio 应用API 的安全鉴权token生成算法

OneNET - 中国移动物联网开放平台 (10086.cn)

"文档中心 /OneNET Studio /应用开发 /应用API /安全鉴权"

安全鉴权

最近更新时间:2022-02-11 16:44:25

准备资料:

  1. accessKey
  2. 用户ID

用户ID 和 accessKey 获取:

先看最终需要生成的结果是什么:

version=2020-05-29&res=userid%2F38055&et=1623982416&method=sha1&sign=S04GcvafYIjtAMHJthkGPevbNwE%3D

组成部分:中间用"&"链接起来

  1. version
  2. res
  3. userid:实际上就是userid/用户id,若用户id为:333333,则userid:"userid/333333"
  4. et
  5. method
  6. sig

sign的组成稍稍有点复杂,先展示一下官方提供的生成公式:

//et、method、res、version都是字符串变量
StringForSignature = et + '\n' + method + '\n' +res + '\n' + version

sign=base64(hmac_<method>(base64decode(accessKey),utf-8(StringForSignature)))

Qt代码实现:

void fun(){
//#-------------------------------------------------
/*
StringForSignature=et+” \n” +method+” \n” +res+” \n”+version
1623982416
SHA256
userid/1
20220501

`sign=base64(hmac_<method>(base64decode(accessKey),utf-8(StringForSignature)))`


1970年1⽉1⽇(00:00:00GMT)Unix时间戳 (UnixTimestamp)
1.什么是时间戳?时间戳是指格林威治时间⾃1970年1⽉1⽇(00:00:00 GMT)⾄当前时间的总秒数。
*/
    qint64 seconds = 0;
    seconds = QDateTime::currentDateTime().toSecsSinceEpoch();
    qDebug() << "Greenwich time in seconds: " << seconds + 3600;

    QString access_key = "填你们自己的access_key ";
    QString et = QString("%1").arg(seconds + 3600);
    QString method = "sha1";
    QString userid = "填你们自己的用户ID";
    QString res = "userid/" + userid;
    QString version = "2020-05-29";

    //步骤1 解码 access_key
    QByteArray key = QByteArray::fromBase64(access_key.toUtf8());
    qDebug() << "key.toHex():" << key.toHex();

    //步骤2 拼接 stringForSignature
    QString stringForSignature = et + '\n' + method + '\n' + res + '\n' + version;
    qDebug() << "stringForSignature:" << stringForSignature;
//    qDebug() << "stringForSignature.toUtf8().toHex():" << stringForSignature.toUtf8().toHex();

    //步骤三  按 Sha1 编码
    QByteArray sign_b = QMessageAuthenticationCode::hash(stringForSignature.toUtf8(),
                                                         key,
                                                         QCryptographicHash::Sha1);


    qDebug() << "sign_b.toHex():" << sign_b.toHex();
    QString sign = QString(sign_b.toBase64()).toUtf8();
    qDebug() << "---------- sign:" << sign;

    //步骤四 url编码
    sign = QUrl::toPercentEncoding(sign);
    res = QUrl::toPercentEncoding(res);
    qDebug() << "---------- sign url encode:" << sign;
    qDebug() << "---------- res url encode:" << res;

    //步骤五 合并
    QString token;
    token += "version=" + version;
    token += "&res=" + res;
    token += "&et=" + et;
    token += "&method=" + method;
    token += "&sign=" + sign;
    qDebug() << "---------- token:" << token;
    //#-------------------------------------------------
}

在第四步中,需要进行url编码

官方提供的Python代码,可以做测试,Qt代码调试以Py代码做验证

    import base64
    import hmac
    import time
    from urllib.parse import quote
    
    def token(user_id,access_key):
    
        version = '2020-05-29'
    
        res = 'userid/%s' % user_id
    
        # 用户自定义token过期时间
        et = str(int(time.time()) + 3600)
    
        # 签名方法,支持md5、sha1、sha256
        method = 'sha1'
    
        # 对access_key进行decode
        key = base64.b64decode(access_key)
    
        # 计算sign
        org = et + '\n' + method + '\n' + res + '\n' + version
        sign_b = hmac.new(key=key, msg=org.encode(), digestmod=method)
        sign = base64.b64encode(sign_b.digest()).decode()
    
        # value 部分进行url编码,method/res/version值较为简单无需编码
        sign = quote(sign, safe='')
        res = quote(res, safe='')
    
        # token参数拼接
        token = 'version=%s&res=%s&et=%s&method=%s&sign=%s' % (version, res, et, method, sign)
    
        return token
    
    
    if __name__ == '__main__':
        user_id = '37715'
        access_key = 'mjgvkTCYTBF6DguxMmm+aV9EkDp2CYfL5jzRTph5Th6KhU8gqZz/cBivPTA7tfY5'
    
        print(token(user_id,access_key))

分析调试心得

  • 运行官方提供的Py代码,然后使用apifox在线调试Get,测试鉴权的正确性提供一个测试工具
  • API调试 - OneNET物联网平台 (10086.cn) 在OneNet中的运维监控-API调试中选择一个接口,我选的是:物模型使用-设备属性记录查询
  • 在apifox上填写好参数就可以调试了,关键是Headers中的Authorization参数,还有其他Params参数,具体参考API调试上面的调试结果-真实请求URL
  • 确认API调试能够正常获取数据,确认将参数填写到apifox上也能够正常Get,准备就绪
  • 修改好Py的相关参数,计算得出Token数据,替换apifox中的Headers中的Authorization参数,如果apifox也能够正常Get,那么就可以开始Qt代码
  • Qt代码上列出的每一步都要确认是否都能和Py代码阶段成果一致,否则没办法在多重编解码中找出问题。
  • Py中对于bytes数据使用print(binascii.hexlify(bytes))输出十六进制,Qt中对于QByteArray使用toHex()输出十六进制,核对两者是否相一致。如果是ascii就直接输出即可。
  • Py和Qt中使用的时间戳都是动态获取的,在调试中,可以将Py和Qt的时间戳固定一个值,这样就可达到编码一致的效果,方便阶段成果对比。
  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值