PHP 和 NodeJS 实现 OneNET MQTTs Token 校验

PHP 和 NodeJS 实现 OneNET MQTTs Token 校验

发表于 2020/04/30 更新于 2020/05/10 369 字 2 分钟
AI 摘要 由 AI 自动生成

|

一晃一年多没有做 OneNET 的相关开发了,最早做过 OneNET 的 MQTT 接入。自从上次用 OneNET 做机房环监后一直稳定运行,也没有继续拓展。

最近又需要对接 OneNET 做一个小项目了,故需要重新学习一下 OneNET,现在看了一下 OneNET 对接入能力进行了整合,原来的 EDP、MQTT、HTTP 协议的设备接入并入了多协议接入,在原 MQTT 协议的基础上,新增了 MQTT 物联网套件,不仅支持设备接入、数据存储、设备管理、设备命令,还支持了设备状态同步、消息分发、规则引擎等功能。

目前 MQTTs 使用 Token 进行鉴权验证,官网上提供了 Python 和 Java 两种语言的算法实现,本文提供了 NodeJS 和 PHP 两种语言的算法实现。

MQTT 物联网套件-Token 算法

res 参数说明

我们预期的 res 是一个字符串,以下是 res 资源格式说明(摘自 OneNET 文档):

场景res 参数格式示例说明
API 访问products/{pid}products/123123配套使用产品 ak
设备连接products/{pid}/devices/{device_name}products/123123/devices/mydev配套使用设备 ak

PHP 实现

PHP 版本:PHP 7.x

/**
 * @name: getToken
 * @msg: MQTTs 安全鉴权 Token
 * @param {string} res
 * @param {string} accessKey
 * @return: string
 */
function getToken($res, $access_key)
{
    $version = '2018-10-31';
    $et = time() + 3600; // 过期时间:一小时后 token 失效
    $method = 'md5';
    $key = base64_decode($access_key);
    $org = $et . "\n" . $method . "\n" . $res . "\n" . $version;
    // 签名
    $sign_b = hash_hmac($method, $org, $key, true);
    $sign = base64_encode($sign_b);
    $sign = urlencode($sign);
    $res = urlencode($res);
    $token = 'version=' . $version . '&res=' . $res . '&et=' . $et . '&method=' . $method . '&sign=' . $sign;

    return $token;
}

NodeJS 实现

NodeJS 版本:NodeJS 8.9

const CryptoJS = require("crypto-js");
const urlencode = require("urlencode");

/**
 * @name: getToken
 * @msg: OneNET MQTTs Token 算法
 * @param {*} res
 * @param {*} access_key
 * @return: token
 */
function getToken(res, access_key) {
  var version = "2018-10-31"; // 参数组版本号
  var et = String(parseInt(Date.now() / 1000) + 3600); // 访问过期时间 expirationTime (有效期为1小时)
  var method = "md5";
  // 对 access_key 进行 base64 解码
  var key = CryptoJS.enc.Base64.parse(access_key);
  // 计算 sign
  var org = et + "\n" + method + "\n" + res + "\n" + version;
  var sign_b = CryptoJS.HmacMD5(org, key);
  // 签名
  var sign = CryptoJS.enc.Base64.stringify(sign_b);
  // url 编码
  sign = urlencode(sign);
  res = urlencode(res);
  // 拼接 token
  var token =
    "version=" +
    version +
    "&res=" +
    res +
    "&et=" +
    et +
    "&method=" +
    method +
    "&sign=" +
    sign;
  return token;
}

如果需要更改 method 加密方法,CryptoJS.Hmac 语句也需要同步修改,对应关系见下表。

methodCryptoJS.Hmac
md5CryptoJS.HmacMD5
sha1CryptoJS.HmacSHA1
sha256CryptoJS.HmacSHA256
作者: 小谈谈
声明: 本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。