设备接入物联网平台之前,需通过身份认证。
目前,平台支持使用设备密钥进行设备身份认证。
# 认证方式
创建产品,然后在该产品下添加设备,获取物联网平台颁发的ProductSecret、DeviceSecret等密钥。设备接入物联网平台时,会使用物联网平台颁发的密钥信息,进行身份认证。
针对不同的使用环境,物联网平台提供以下四种设备密钥认证方案。
一机一密:每台设备烧录自己的设备证书(ProductKey、DeviceName和DeviceSecret)。
一型一密预注册:同一产品下设备烧录相同产品证书(ProductKey和ProductSecret)。开通产品的动态注册功能,设备通过动态注册获取DeviceSecret。
两种方案在易用性和安全性上各有优势,您可以根据设备所需的安全等级和实际的产线条件灵活选择。
对比项 | 一机一密 | 一型一密 |
---|---|---|
设备端烧录信息 | ProductKey、DeviceName、DeviceSecret | ProductKey、ProductSecret |
云端是否需要开启动态注册 | 无需开启,默认支持。 | 需打开动态注册开关。 |
是否需要提前在物联网平台创建设备,注册DeviceName | 需要,产品下DeviceName唯一。 | 需要,产品下DeviceName唯一。 |
产线烧录要求 | 逐一烧录设备证书,需确保设备证书的安全性。 | 批量烧录相同的产品证书,需确保产品证书的安全存储。 |
安全性 | 较高 | 一般 |
# 认证流程
设备端使用平台生成的设备密钥,按认证签名算法生成签名,向物联网平台请求鉴权,获取设备连接平台使用的真实配置信息
认证通过,平台返回连接地址、用户名、密码等信息,设备使用以上信息连接平台。
设备端根据需要可以将获得的连接信息持久化保存到设备中,之后再连接平台时可以直接使用,而无需每次都请求认证接口获取连接信息,此时需要开启产品的永久密钥开关以及在认证时选择返回永久密钥。
# 一机一密认证方法
一机一密认证要求设备烧录自身的密钥,密钥与设备一对一绑定,每个设备的密钥不同。
# 签名计算
- 将接口路径、分钟级时间戳和请求参数(body的JOSN字符串)拼接成待加密字符串authStringPrefix,参数之间以换行符"\n"连接,没有请求参数时,填"null"
示例: /v1/devices/zfm8n1p5y1qzc09a/test01/test01/resources 26944410 {"resourceType":"MQTT"} 或 /v1/devices/zfm8n1p5y1qzc09a/test01/test01/resources 26944410 null
分别获取deviceSecret、authStringPrefix的字节数组
使用deviceSecret字节数组对上述认证字符串字节数组进行HmacSHA256进行加密
将加密后的byte数组进行Base64编码得到signature,并进行urlencode处理
将最终得到的signature和分钟级时间戳放到请求的header中
不同编程语言实现签名算法时,对字符串的处理方法存在差异,以下两点需特别注意:
body json string不要带空格,如python的json.dumps()为了美观会加上空格,导致鉴权失败,请指定参数separators=(',','😂
urlencode处理时需对全部字符进行转换,例如python中使用urllib.parse.quote()时默认不对‘/’进行编码,需要是应用urllib.parse.quote('待转换字符串', safe='')
# 请求鉴权
认证地址: 在平台控制台实例详情页获取,认证地址在不同的项目中可能不一致
Path: /v1/devices/{instanceId}/{productkey}/{deviceName}/resources
Method: POST
Headers
参数名称 | 参数值 | 是否必须 | 示例 | 备注 |
---|---|---|---|---|
Content-Type | application/json | 是 | ||
signature | 是 | |||
expiryTime | 是 | 分钟级时间戳,当前时间前后十分钟有效 |
路径参数
参数名称 | 示例 | 备注 |
---|---|---|
instanceId | 平台实例ID | |
productkey | 产品标识 | |
deviceName | 设备标识 |
Body
名称 | 类型 | 是否必须 | 默认值 | 备注 |
---|---|---|---|---|
resourceType | string | 必须 | 无 | MQTT/EVS |
# 返回参数
名称 | 类型 |
---|---|
resourceType | string |
content | object |
# 返回示例
{
"resourceType":"MQTT",
"content":{
"password":"418b803b0dc12206a6438901ad814",
"clientId":"a63c3cd470bc27ff287f3dcac45b",
"port":1883,
"broker":"ahvmcra.iot.gz.AIoTbce.com",
"username":"thingidp@ahvmcra|a63c3cd470bc27ff287f3dcac45b|0|MD5"
}
}
# 一型一密认证方法
一型一密认证时设备烧录统一的产品密钥,同一产品下不同设备烧录相同密钥,并在认证时携带产品密钥及设备唯一标识换取一机一密密钥。一型一密在产线批量烧录的场景下更加简便,同时需注意保护产品线密钥不要泄露。
# 签名计算
- 将接口路径、分钟级时间戳和请求参数(body的JOSN字符串)拼接成待加密字符串authStringPrefix,参数之间以换行符"\n"连接,没有请求参数时,填"null"
示例: /v1/devices/zfm8n1p5y1qzc09a/test01/test01/register 26944410 null
分别获取productSecret、authStringPrefix的字节数组
使用productSecret字节数组对上述认证字符串字节数组进行HmacSHA256进行加密
将加密后的byte数组进行Base64编码得到signature,并进行urlencode处理
将最终得到的signature和分钟级时间戳放到请求的header中
不同编程语言实现签名算法时,对字符串的处理方法存在差异,以下两点需特别注意:
body json string不要带空格,如python的json.dumps()为了美观会加上空格,导致鉴权失败,请指定参数separators=(',','😂
urlencode处理时需对全部字符进行转换,例如python中使用urllib.parse.quote()时默认不对‘/’进行编码,需要是应用urllib.parse.quote('待转换字符串', safe='')
# 请求设备注册鉴权
认证地址: 与一机一密一致
Path: /v1/devices/{instanceId}/{productkey}/{deviceName}/register
Method: POST
Headers
参数名称 | 参数值 | 是否必须 | 示例 | 备注 |
---|---|---|---|---|
Content-Type | application/json | 是 | ||
signature | 是 | |||
expiryTime | 是 | 分钟级时间戳,当前时间前后十分钟有效 | ||
algorithmType | 非 | [DEFAULT, SHC],非必须 |
路径参数
参数名称 | 示例 | 备注 |
---|---|---|
instanceId | 平台实例ID | |
productkey | 产品标识 | |
deviceName | 设备标识 |
Body
{}
# 返回参数
名称 | 类型 |
---|---|
deviceSecret | string |
# 返回示例
{
"deviceSecret":"418b803b0dc12206a6438901ad814"
}
# 请求设备鉴权
设备通过一型一密鉴权获得设备密钥后,继续使用此密钥按一机一密认证流程进行认证