第 1-2 课:设备注册(一)

在本节中,我们将设计 IotHub 的设备认证机制。

设备三元组

EMQ X 在默认的情况是允许匿名连接的,所以在上一节课程中,IotDevice类在连接 MQTT Broker 的时候没有指定 username 和 password 也能成功。

当然,我们肯定不希望任意一个设备都能连接到 Maque IotHub。首先我们需要到 Maque IotHub 注册一个设备,然后设备再通过由 Maque IotHub 下发的 username/password 连接到 Maque IotHub,以实现一机一密。

阿里云 IoT 平台用一个三元组(ProductKey, DeviceName, Secret)来标识一个逻辑上的设备,ProductKey 是指设备所属的产品,DeviceName 用来标识这个设备的唯一名称,Secret 是指这个设备连接物联网平台使用的密码。我认为这是一个很好的设计,因为即使在同一家公司内部,往往也会有多个服务不同业务的物联网产品需要接入,所以多一个 ProductKey 对后续的主题名、数据存储和分发等进行一个区分是很有必有的。

Maque IotHub 将使用类似的三元组(ProductName, DeviceName, Secret)来标识逻辑上的一台设备。ProductName由业务系统提供,可以是一个有意义的 ASCII 字符串,DeviceName 由 IotHub 自动生成,(ProductName, DeviceName)应该是全局唯一的。

这里我们约定,对一个设备(ProductName1, DeviceName1, Secret1),它接入 Maque IotHub 的 username 为 ProductName1/DeviceName1,password 为 Secret1

为什么说三元组标识的是逻辑上的一台设备而不是物理上的一台设备? 比如说:移动应用接入 Maque IotHub 来订阅某个主题,假如有一个用户在多个移动设备上用同一个账号登录,他使用的应该是同一个三元组,因为他订阅的消息在每个设备上都应该能收到,那么在这种情况下一个三元组实际上是对应多个物理设备。后面我们再来讲怎么来区分物理设备。

为什么要用"/"做分隔符,这里先不作说明,在讲到下行数据处理的部分再来解释。

EMQ X 认证方式

EMQ X 通过插件提供了多种灵活的认证方式,你可以在这里找到 EMQ X 自带的插件列表,Maque IotHub 使用 MongoDB 作为数据存储,所以这里我们选择 MongoDB 认证插件。除了使用 MongoDB 认证以外,我们还会使用 JWT 的认证方式来提供一种临时性的接入认证。

在启用认证插件之前,我们需要关闭 EMQ X 的默认匿名认证。

编辑 <EMQ X 安装目录>/etc/emqx.conf,修改以下配置项:

allow_anonymous = false

然后重新启动 EMQ X <EMQ X 安装目录>/bin/emqx restart

MongoDB 认证

MongoDB 的认证插件功能逻辑很简单:将设备的 username、password 存储在 MongoDB 的某个 Collection 中,当设备发起 Connect 的时候,Broker 再查找这个 Collection,如果 username/password 能匹配得上,则允许连接,否则拒绝连接。

<EMQ X 安装目录>/etc/plugins/emqx_auth_mongo.conf 可以对 MongoDB 认证进行配置,配置项很多,在这里我们看几个关键的配置项。

  • MongoDB 地址: auth.mongo.server = 127.0.0.1:27017
  • 用于认证的数据库: auth.mongo.database = mqtt 存储设备 username 和 password 的数据库,这里暂时用默认值。
  • 用于认证的 Collection: auth.mongo.auth_query.collection = mqtt_user 存储设备 username 和password 的 Collection, 这里暂时使用默认值。
  • password 字段名: auth.mongo.auth_query.password_field = password
  • password 加密方式: auth.mongo.auth_query.password_hash = plain, password 字段的加密方式,这里选择不加密。
  • 是否打开超级用户查询: auth.mongo.super_query = off,设置为关闭。
  • 是否打开权限查询: auth.mongo.acl_query = off,这里我们暂时不打开 Publish 和 Subscribe 的权限控制。

然后我们在 MongoDB 插入一条记录,在 MongoDB Shell 中运行:

use mqtt
db.createCollection("mqtt_user")
db.mqtt_user.insert({username: "test", password: "123456"})

然后加载 MongoDB 认证插件:

<EMQ X 安装目录>/bin/emqx_ctl plugins load emqx_auth_mongo

不出意外的话控制台会输出:

Start apps: [emqx_auth_mongo]
Plugin emqx_auth_mongo loaded successfully.

这个时候如果我们运行 test_mqtt.js,会得到以下输出: Error: Connection refused: Bad username or password

接下来,我们在连接的时候指定刚才存储在 MongoDB 的 username/password: test/123456

...

var client = mqtt.connect('mqtt://127.0.0.1:1883', {
    username: "test",
    password: "123456"
})

...

重新运行 test_mqtt.js,如果

return code: 0

说明基于 MongoDB 的认证方式已经生效了。

如果返回的是Error: Connection refused: Bad username or password,你需要检查:

  • 插件的配置文件是否按照课程中的方式进行配置;
  • MongoDB 插件是否成功加载,可通过运行 <EMQ X 安装目录>/bin/emqx_ctl plugins load emqx_auth_mongo 查看;
  • 对应的设备数据是否添加到 MongoDB 对应的 collection 中。

可以通过运行<EMQ X 安装目录>/bin/emqx_ctl plugins list方式查看插件列表,已加载的插件会显示 active=true。

JWT (JSON Web Token) 认证

使用 MongoDB 认证插件已经能够满足我们对设备注册的需求,但是我在这里还想再引入一种新的认证方式:JWT 认证。为什么呢?考虑以下两个场景:

  • 在浏览器中,使用 WebSocket 方式进行接入时,你需要将接入 Maque IotHub 的 username 和 password 传给前端的 js 的代码,那么在浏览器的 Console 里就可以看见 username 和 password,这非常不安全。如果使用 JWT 认证方式,你只需要将一段有效期很短的 JWT 传给前端的 js 代码,即使泄露了,可以操作的时间窗口也很短。
  • 有时候你需要绕过注册设备这个流程来连接到 Maque IotHub,EMQ X 会在一些内部的系统主题上发布与 Broker 相关的状态信息,比如连接数、消息数等。如果你需要用一个 Client 连接到 Maque IotHub 并订阅这些主题的话,先创建一个 Device 并不是很好的选择,这种情况下,用 JWT 作为一次性的密码为这些系统内部的接入做认证就会非常好。

JSON Web Token(JWT,读作 [/dʒɒt/]),是一种基于 JSON 的、用于在网络上声明某种主张的令牌(Token),更详细的介绍可以参考 jwt.io

EMQ X 提供了 JWT 认证插件来提供 JWT 方式的认证,在<EMQ X 安装目录>/etc/plugins/emqx_auth_mongo.conf 可以对 JWT 认证插件进行配置:

  • JWT Secret: auth.jwt.secret = emqxsecret, 这里我们使用默认值,当然在实际生产中你需要使用一个长且复杂的字符串。
  • 是否开启 Claim 验证: auth.jwt.verify_claims = on 打开 Claim 验证。
  • Claim 验证字段: auth.jwt.verify_claims.username = %u 需要验证 Claim 中的 username 字段。

下面我们来看下如何使用 JWT 来接入 Maque IotHub:

...

var jwt = require('jsonwebtoken')
var password = jwt.sign({
    username: "jwt_user",
    exp: Math.floor(Date.now() / 1000) + 10
}, "emqxsecret")
var client = mqtt.connect('mqtt://127.0.0.1:1883', {
    username: "jwt_user",
    password: password
})

...

在这里我们使用 EMQ X 预设的 JWT Secret 签发了一个有效期为 10 秒的 JWT token 进行连接,重新运行 test_mqtt.js,如果输出为:

return code: 0

说明基于 JWT 的认证方式已经生效了。

如果返回的是Error: Connection refused: Bad username or password,你需要检查:

  • 插件的配置文件是否按照课程中的方式进行配置;
  • JWT插件是否成功加载,可通过运行 <EMQ X 安装目录>/bin/emqx_ctl plugins list 查看;
  • 是否是使用课程中指定的 payload 来生成 JWT 的。
认证链

我们加载了 MongoDB 和 JWT 两个认证插件,EMQ X 就可以用这两个插件组成的认证链来对接入的 Client 进行认证。简单来说,设备既可以使用存储在 MongoDB 里的 username 和 password,也可以使用 JWT 来接入 EMQ X Broker。

EMQ X 在加载一个插件后,会把这个插件的名字写入 <EMQ X 安装目录>/data/loaded_plugins, EMQ X 在每次启动时都会自动加载这个文件里面包含的插件,所以我们只需要手动加载一次这两个插件就可以了。


在这一节我们讨论了 Maque IotHub 中设备的认证方式,以及 EMQ X 是如何支持这些认证方式的。下一节我们会写一些代码,把这些功能集成到 Maque IotHub 的设备注册流程中去。

**推荐阅读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sufish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值