如何在不使用 SDK 的情況下透過 HTTPS 使用對稱金鑰
在本操作說明文章中,您將透過 HTTPS 使用對稱金鑰布建裝置,而不需使用 Azure IoT DPS 裝置 SDK。 大部分的語言都提供連結庫來傳送 HTTP 要求,但在本文中,您將使用 cURL 命令行工具來透過 HTTPS 傳送和接收特定語言。
您可以依照本文中的步驟,在 Linux 或 Windows 計算機上執行。 如果您在 Windows 子系統 Linux 版 (WSL) 上執行或在 Linux 電腦上執行,您可以在 Bash 提示字元中輸入本機系統上的所有命令。 如果您在 Windows 上執行,請在 GitBash 提示字元中輸入本機系統上的所有命令。
根據您選擇的註冊項目類型而定,本文有不同的路徑。 安裝必要條件之後,請務必先閱讀概 觀 再繼續進行。
必要條件
如果您沒有 Azure 訂用帳戶,請在開始前建立免費帳戶。
使用 Azure 入口網站 完成設定 IoT 中樞 裝置布建服務中的步驟。
請確定 您的電腦已安裝 Python 3.7 或更新版本。 您可以執行
python --version
來檢查 Python 版本。如果您在 Windows 中執行,請安裝最新版本的 Git。 請確定 Git 已新增至命令視窗可存取的環境變數。 請參閱 Software Freedom Conservancy 的 Git 用戶端工具 ,以取得要安裝之最新版
git
的工具,其中包括 Git Bash,您可以用來與本機 Git 存放庫互動的命令行應用程式。 在 Windows 上,您會在 GitBash 提示字元中輸入本機系統上的所有命令。Azure CLI。 您有兩個選項可用來執行本文中的 Azure CLI 命令:
- 使用 Azure Cloud Shell,這是在瀏覽器中執行 CLI 命令的互動式殼層。 建議您使用此選項,因為您不需要安裝任何專案。 如果您是第一次使用 Cloud Shell,請登入 Azure 入口網站。 請遵循 Cloud Shell 快速入門中的步驟來啟動 Cloud Shell 並選取 Bash 環境。
- 您可以選擇性地在本機電腦上執行 Azure CLI。 如果已安裝 Azure CLI,請執行
az upgrade
以將 CLI 和擴充功能升級至目前的版本。 若要安裝 Azure CLI,請參閱 安裝 Azure CLI。
如果您是在Linux或 WSL 環境中執行,請開啟Bash提示字元以在本機執行命令。 如果您是在 Windows 環境中執行,請開啟 GitBash 提示字元。
概觀
在本文中,您可以使用 個別註冊 或 註冊群組 ,透過 DPS 布建。
建立個別註冊或註冊群組項目之後,請繼續 建立 SAS 令牌 ,並使用 DPS 註冊您的裝置 。
使用個別註冊
如果您想要建立要用於本文的新個別註冊,您可以使用 az iot dps enrollment create 命令來建立對稱密鑰證明的個別註冊。
下列命令會為您的 DPS 實例建立具有預設配置原則的註冊專案,並讓 DPS 為您的裝置指派主要和次要密鑰:
az iot dps enrollment create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --attestation-type symmetrickey
取代您的資源群組和 DPS 實例名稱。
註冊標識碼是裝置的註冊標識碼。 註冊標識碼是英數位元的不區分大小寫字串(最多 128 個字元長),加上特殊字元:
'-'
、、'.'
、'_'
':'
。 最後一個字元必須是英數位元或虛線 ('-'
)。 請確定您在命令中使用的註冊識別碼遵守此格式。
指派的對稱金鑰會在回應的證明屬性中傳回:
{
"allocationPolicy": null,
"attestation": {
"symmetricKey": {
"primaryKey": "G3vn0IZH9oK3d4wsxFpWBtd2KUrtjI+39dZVRf26To8w9OX0LaFV9yZ93ELXY7voqHEUsNhnb9bt717UP87KxA==",
"secondaryKey": "4lNxgD3lUAOEOied5/xOocyiUSCAgS+4b9OvXLDi8ug46/CJzIn/3rN6Ys6gW8SMDDxMQDaMRnIoSd1HJ5qn/g=="
},
"tpm": null,
"type": "symmetricKey",
"x509": null
},
...
}
記下個別註冊專案的主要金鑰和註冊標識碼(註冊標識元),您將在本文稍後使用。
如果您想要使用本文的現有個別註冊,您可以使用 az iot dps enrollment show 命令取得主鍵:
az iot dps enrollment show -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --show-keys true
使用註冊群組
如果您想要建立要用於本文的新註冊群組,您可以使用 az iot dps enrollment-group create 命令來建立對稱密鑰證明的註冊群組。
下列命令會為您的 DPS 實例建立具有預設配置原則的註冊群組專案,並讓 DPS 為註冊群組指派主要和次要密鑰:
az iot dps enrollment-group create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id}
取代您的資源群組和 DPS 實例名稱。
註冊標識碼是英數位元的不區分大小寫字串(最多 128 個字元長),加上特殊字元:
'-'
、、'.'
、'_'
':'
。 最後一個字元必須是英數位元或虛線 ('-'
)。 它可以是您選擇用於註冊群組的任何名稱。
指派的對稱金鑰會在回應的證明屬性中傳回:
{
"allocationPolicy": null,
"attestation": {
"symmetricKey": {
"primaryKey": "G3vn0IZH9oK3d4wsxFpWBtd2KUrtjI+39dZVRf26To8w9OX0LaFV9yZ93ELXY7voqHEUsNhnb9bt717UP87KxA==",
"secondaryKey": "4lNxgD3lUAOEOied5/xOocyiUSCAgS+4b9OvXLDi8ug46/CJzIn/3rN6Ys6gW8SMDDxMQDaMRnIoSd1HJ5qn/g=="
},
"tpm": null,
"type": "symmetricKey",
"x509": null
},
...
}
記下主鍵。
如果您想要使用本文的現有個別註冊,您可以使用 az iot dps enrollment-group show 命令取得主鍵:
az iot dps enrollment-group show -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --show-keys true
衍生裝置金鑰
搭配群組註冊使用對稱密鑰證明時,您不會直接使用註冊群組密鑰。 相反地,您會從註冊群組密鑰衍生每個裝置的唯一密鑰。 如需詳細資訊,請參閱 使用對稱密鑰群組註冊。
在本節中,您將從註冊群組主鍵產生裝置密鑰,以計算裝置唯一 註冊標識碼的 HMAC-SHA256 。 結果接著會轉換成Base64格式。
使用 openssl 產生您的唯一索引鍵。 您將使用下列 Bash 殼層腳稿。
{primary-key}
取代為您稍早複製的註冊群組主要金鑰,並以您要用於裝置的註冊識別碼取代{contoso-simdevice}
。 註冊標識碼是英數位元的不區分大小寫字串(最多 128 個字元長),加上特殊字元:'-'
、、'.'
、'_'
':'
。 最後一個字元必須是英數位元或虛線 ('-'
)。KEY={primary-key} REG_ID={contoso-simdevice} keybytes=$(echo $KEY | base64 --decode | xxd -p -u -c 1000) echo -n $REG_ID | openssl sha256 -mac HMAC -macopt hexkey:$keybytes -binary | base64
文稿會輸出類似下列索引鍵的內容:
p3w2DQr9WqEGBLUSlFi1jPQ7UWQL4siAGy75HFTFbf8=
記下衍生的裝置金鑰和您用來產生它的註冊識別碼,您將在下一節中使用它們。
您也可以使用 Azure CLI 或 PowerShell 來衍生裝置密鑰。 若要深入瞭解,請參閱 衍生裝置密鑰。
建立 SAS 令牌
使用對稱金鑰證明時,裝置會使用共用存取簽章 (SAS) 令牌向 DPS 進行驗證。 針對透過個別註冊佈建的裝置,令牌會使用註冊項目中設定的主要或次要密鑰進行簽署。 針對透過註冊群組佈建的裝置,令牌會使用衍生的裝置密鑰進行簽署,接著會使用註冊群組專案中的主要或次要密鑰集來產生令牌。 令牌會指定到期時間和目標資源 URI。
下列 Python 腳本可用來產生 SAS 令牌:
from base64 import b64encode, b64decode
from hashlib import sha256
from time import time
from urllib.parse import quote_plus, urlencode
from hmac import HMAC
def generate_sas_token(uri, key, policy_name, expiry=3600):
ttl = time() + expiry
sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl))
print(sign_key)
signature = b64encode(HMAC(b64decode(key), sign_key.encode('utf-8'), sha256).digest())
rawtoken = {
'sr' : uri,
'sig': signature,
'se' : str(int(ttl))
}
if policy_name is not None:
rawtoken['skn'] = policy_name
return 'SharedAccessSignature ' + urlencode(rawtoken)
uri = '[resource_uri]'
key = '[device_key]'
expiry = [expiry_in_seconds]
policy= '[policy]'
print(generate_sas_token(uri, key, policy, expiry))
其中:
[resource_uri]
是您嘗試使用此令牌存取之資源的 URI。 針對 DPS,其格式[dps_id_scope]/registrations/[dps_registration_id]
為 ,其中[dps_id_scope]
是 DPS 實例的識別碼範圍,而[dps_registration_id]
是您用於裝置的註冊標識碼。您可以從 Azure 入口網站 中實例的 [概觀] 窗格取得 DPS 實例的標識符範圍,也可以使用 az iot dps show Azure CLI 命令(將佔位符取代為您的資源組名和 DPS 實例):
az iot dps show -g {resource_group_name} --name {dps_name}
[device_key]
是與您的裝置相關聯的裝置密鑰。 此金鑰是個別註冊中為您指定的或自動產生的金鑰,或群組註冊的衍生密鑰。[expiry_in_seconds]
是此 SAS 令牌的有效期間,以秒為單位。[policy]
是與裝置密鑰相關聯的原則。 針對 DPS 裝置註冊,原則會硬式編碼為「註冊」。
名為 my-symkey-device
且有效期間為 30 天的裝置輸入範例集可能如下所示。
uri = '0ne00111111/registrations/my-symkey-device'
key = '18RQk/hOPJR9EbsJlk2j8WA6vWaj/yi+oaYg7zmxfQNdOyMSu+SJ8O7TSlZhDJCYmn4rzEiVKIzNiVAWjLxrGA=='
expiry = 2592000
policy='registration'
修改裝置和 DPS 實例的腳本,並將其儲存為 Python 檔案;例如, generate_token.py。 執行文稿, 例如 python generate_token.py
。 它應該會輸出類似下列的 SAS 令牌:
0ne00111111%2Fregistrations%2Fmy-symkey-device
1663952627
SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration
複製並儲存以 開頭的 SharedAccessSignature
整行。 這一行是SAS令牌。 在下列各節中,您將需要用到它。
若要深入瞭解如何搭配 DPS 使用 SAS 令牌及其結構,請參閱 使用 SAS 控制 DPS 的存取權。
註冊您的裝置
您可以呼叫 註冊裝置 REST API,以透過 DPS 布建裝置。
使用下列 curl 命令:
curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -H 'Authorization: [sas_token]' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31
其中:
-L
指示 curl 遵循 HTTP 重新導向。–i
指示 curl 在輸出中包含通訊協議標頭。 這些標頭並非絕對必要,但它們可能很有用。-X PUT
告知 curl 這是 HTTP PUT 命令。 此 API 呼叫的必要專案。-H 'Content-Type: application/json'
告知 DPS 我們正在張貼 JSON 內容,而且必須是 『application/json』。-H 'Content-Encoding: utf-8'
告知 DPS 我們用於訊息本文的編碼方式。 設定為 OS/客戶端的適當值;不過,通常是utf-8
。-H 'Authorization: [sas_token]'
告知 DPS 使用您的 SAS 令牌進行驗證。 將 [sas_token] 取代為您在建立 SAS 令牌中 產生的令牌。-d '{"registrationId": "[registration_id]"}'
,參數–d
是我們張貼之訊息的「數據」或本文。 它必須是 JSON,格式為 '{“registrationId”:“[registration_id”}'。 請注意,對於 curl,它會以單引弧括住;否則,您必須逸出 JSON 中的雙引號。最後,最後一個參數是要張貼至 的 URL。 針對「一般」(亦即非內部部署)DPS,會使用全域 DPS 端點 global.azure-devices-provisioning.net:
https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31
。 請注意,您必須將 和[registration_id]
取代[dps_scope_id]
為適當的值。
例如:
curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -H 'Authorization: SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration' -d '{"registrationId": "my-symkey-device"}' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/register?api-version=2021-06-01
成功的呼叫會有類似下列的回應:
HTTP/1.1 202 Accepted
Date: Wed, 31 Aug 2022 22:02:49 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Location: https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/register
Retry-After: 3
x-ms-request-id: a021814f-0cf6-4ce9-a1e9-ead7eb5118d9
Strict-Transport-Security: max-age=31536000; includeSubDomains
{"operationId":"5.316aac5bdc130deb.b1e02da8-c3a0-4ff2-a121-7ea7a6b7f550","status":"assigning"}
回應包含作業標識碼和狀態。 在這裡情況下,狀態會設定為 assigning
。 DPS 註冊可能是長時間執行的作業,因此會以異步方式完成。 一般而言,您將使用 作業狀態查閱 REST API 輪詢 狀態,以判斷裝置是否已指派或是否發生失敗。
DPS 的有效狀態值如下:
assigned
:狀態呼叫的傳回值會指出已指派裝置 IoT 中樞 的內容。assigning
:作業仍在執行中。disabled
:D PS 中已停用註冊記錄,因此無法指派裝置。failed
:指派失敗。 回應中registrationState
將會傳errorCode
回 並errorMessage
傳回 ,以指出失敗的內容。unassigned
若要呼叫 作業狀態查閱 API,請使用下列 curl 命令:
curl -L -i -X GET -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -H 'Authorization: [sas_token]' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/operations/[operation_id]?api-version=2019-03-31
您將使用與註冊裝置要求中相同的標識碼範圍、註冊標識碼和SAS令牌。 使用註冊裝置回應中傳回的作業標識碼。
例如:
curl -L -i -X GET -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -H 'Authorization: SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/operations/5.316aac5bdc130deb.f4f1828c-4dab-4ca9-98b2-dfc63b5835d6?api-version=2021-06-01
下列輸出顯示已成功指派之裝置的回應。 請注意, status
屬性是 assigned
,而且 registrationState.assignedHub
屬性會設定為布建裝置的IoT中樞。
HTTP/1.1 200 OK
Date: Wed, 31 Aug 2022 22:05:23 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
x-ms-request-id: ffb98d42-023e-4e75-afb0-1807ff091cbb
Strict-Transport-Security: max-age=31536000; includeSubDomains
{
"operationId":"5.316aac5bdc130deb.b1e02da8-c3a0-4ff2-a121-7ea7a6b7f550",
"status":"assigned",
"registrationState":{
"registrationId":"my-symkey-device",
"createdDateTimeUtc":"2022-08-31T22:02:50.5163352Z",
"assignedHub":"MyExampleHub.azure-devices.net",
"deviceId":"my-symkey-device",
"status":"assigned",
"substatus":"initialAssignment",
"lastUpdatedDateTimeUtc":"2022-08-31T22:02:50.7370676Z",
"etag":"IjY5MDAzNTUyLTAwMDAtMDMwMC0wMDAwLTYzMGZkYThhMDAwMCI="
}
}
傳送遙測訊息
您必須先為指派裝置的IoT中樞建立SAS令牌,才能傳送遙測訊息。 您可以使用用來簽署 DPS 實例 SAS 令牌的相同主要金鑰或衍生裝置金鑰來簽署此權杖。
為您的IoT中樞建立SAS令牌
若要建立 SAS 令牌,您可以執行相同的程式代碼,以下列變更建立 DPS 實例的令牌:
uri = '[resource_uri]'
key = '[device_key]'
expiry = [expiry_in_seconds]
policy= None
其中:
[resource_uri]
是您嘗試使用此令牌存取之資源的 URI。 針對將訊息傳送至 IoT 中樞的裝置,其格式[iot-hub-host-name]/devices/[device-id]
為 。針對
[iot-hub-host-name]
,請使用上一節中 屬性中所assignedHub
傳回 IoT 中樞 主機名。針對
[device-id]
,請使用上一節中 屬性中傳回的deviceId
裝置標識碼。
[device_key]
是與您的裝置相關聯的裝置密鑰。 此金鑰是個別註冊中為您指定的或自動產生的金鑰,或群組註冊的衍生密鑰。 (這是您先前用來建立 DPS 令牌的相同金鑰。[expiry_in_seconds]
是此 SAS 令牌的有效期間,以秒為單位。policy=None
將遙測傳送至IoT中樞的裝置不需要任何原則,因此此參數會設定為None
。
名為 傳送 IoT 中樞 至名為 MyExampleHub
且令牌有效期間為一小時的裝置輸入範例集my-symkey-device
,可能如下所示:
uri = 'MyExampleHub.azure-devices.net/devices/my-symkey-device'
key = '18RQk/hOPJR9EbsJlk2j8WA6vWaj/yi+oaYg7zmxfQNdOyMSu+SJ8O7TSlZhDJCYmn4rzEiVKIzNiVAWjLxrGA=='
expiry = 3600
policy= None
下列輸出顯示這些輸入的範例 SAS 令牌:
SharedAccessSignature sr=MyExampleHub.azure-devices.net%2Fdevices%2Fmy-symkey-device&sig=f%2BwW8XOKeJOtiPc9Iwjc4OpExvPM7NlhM9qxN2a1aAM%3D&se=1663119026
若要深入瞭解如何為 IoT 中樞 建立 SAS 令牌,包括其他程式設計語言中的範例程式代碼,請參閱使用共用存取簽章控制對 IoT 中樞 的存取。
注意
為了方便起見,您可以使用 Azure CLI az iot hub generate-sas-token 命令來取得向 IoT 中樞註冊之裝置的 SAS 令牌。 例如,下列命令會產生一小時的SAS令牌。 {iothub_name}
針對 ,您只需要主機火腿的第一個部分,例如 MyExampleHub
。
az iot hub generate-sas-token -d {device_id} -n {iothub_name}
將數據傳送至IoT中樞
您可以呼叫 IoT 中樞 傳送裝置事件 REST API,以將遙測傳送至裝置。
使用下列 curl 命令:
curl -L -i -X POST -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -H 'Authorization: [sas_token]' -d '{"temperature": 30}' https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13
其中:
-X POST
告知 curl 這是 HTTP POST 命令。 此 API 呼叫的必要專案。-H 'Content-Type: application/json'
告知 IoT 中樞 我們張貼 JSON 內容,而且必須是 『application/json』。-H 'Content-Encoding: utf-8'
會告知 IoT 中樞 訊息本文所使用的編碼方式。 設定為 OS/客戶端的適當值;不過,通常是utf-8
。-H 'Authorization: [sas_token]'
告知 IoT 中樞 使用您的 SAS 令牌進行驗證。 將取代[sas_token]
為您為指派的IoT中樞所產生的令牌。-d '{"temperature": 30}'
,參數–d
是我們張貼之訊息的「數據」或本文。 在本文中,我們會張貼單一溫度數據點。 內容類型已指定為 application/json,因此,針對此要求,本文為 JSON。 請注意,對於 curl,它會以單引弧括住;否則,您必須逸出 JSON 中的雙引號。最後一個參數是要張貼至的URL。 針對傳送裝置事件 API,URL 為:
https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13
。將取代
[assigned_iot_hub_name]
為您裝置指派給的IoT中樞名稱。將取代
[device_id]
為您註冊裝置時所指派的裝置識別碼。 對於透過註冊群組布建的裝置,裝置標識碼將會是註冊標識碼。 針對個別註冊,您可以選擇性地指定與註冊專案中註冊標識碼不同的裝置標識碼。
例如,若裝置標識碼為 my-symkey-device
將遙測數據點傳送至名為 MyExampleHub
的IoT中樞,
curl -L -i -X POST -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -H 'Authorization: SharedAccessSignature sr=MyExampleHub.azure-devices.net%2Fdevices%2Fmy-symkey-device&sig=f%2BwW8XOKeJOtiPc9Iwjc4OpExvPM7NlhM9qxN2a1aAM%3D&se=1663119026' -d '{"temperature": 30}' https://MyExampleHub.azure-devices.net/devices/my-symkey-device/messages/events?api-version=2020-03-13
成功的呼叫會有類似下列的回應:
HTTP/1.1 204 No Content
Content-Length: 0
Vary: Origin
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: 9e278582-3561-417b-b807-76426195920f
Date: Wed, 14 Sep 2022 00:32:53 GMT