簽署 HTTP 要求
在本教學課程中,您將了解如何使用 HMAC 簽章來簽署 HTTP 要求。
注意
強烈建議使用 Azure SDK。 此處所述的方法為後援選項,適用於 Azure SDK 因任何原因而無法使用的情況。
必要條件
開始之前,請務必:
- 建立具有有效訂閱的 Azure 帳戶。 如需詳細資訊,請參閱免費建立帳戶。
- 安裝 Visual Studio。
- 建立 Azure 通訊服務資源。 如需詳細資訊,請參閱建立 Azure 通訊服務資源。 在本教學課程中,您必須記錄 resourceEndpoint 和 resourceAccessKey。
使用 C# 簽署 HTTP 要求
存取金鑰驗證會使用共用的秘密金鑰,為每個 HTTP 要求產生 HMAC 簽章。 此簽章是使用 SHA256 演算法所產生,並使用 HMAC-SHA256
配置在 Authorization
標頭中傳送。 例如:
Authorization: "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=<hmac-sha256-signature>"
hmac-sha256-signature
包含:
- HTTP 動詞指令 (例如
GET
或PUT
) - HTTP 要求路徑
- x-ms-date
- Host
- x-ms-content-sha256
設定
下列步驟說明如何建構授權標頭。
建立新的 C# 應用程式
在主控台視窗中 (例如 cmd、PowerShell 或 Bash),使用 dotnet new
命令建立名為 SignHmacTutorial
的新主控台應用程式。 此命令會建立簡單的 "Hello World" C# 專案,內含單一原始程式檔:Program.cs。
dotnet new console -o SignHmacTutorial
將目錄變更為新建立的應用程式資料夾。 使用 dotnet build
命令來編譯您的應用程式。
cd SignHmacTutorial
dotnet build
Install the package
安裝用於主體序列化的套件 Newtonsoft.Json
。
dotnet add package Newtonsoft.Json
更新 Main
方法宣告以支援非同步程式碼。 使用下列程式碼開始作業。
using System;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace SignHmacTutorial
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Azure Communication Services - Sign an HTTP request Tutorial");
// Tutorial code goes here.
}
}
}
建立要求訊息
在此範例中,我們將使用通訊服務驗證 API (2021-03-07
版) 來簽署建立新身分識別的要求。
將下列程式碼新增至 Main
方法。
string resourceEndpoint = "resourceEndpoint";
// Create a uri you are going to call.
var requestUri = new Uri($"{resourceEndpoint}/identities?api-version=2021-03-07");
// Endpoint identities?api-version=2021-03-07 accepts list of scopes as a body
var body = new
{
createTokenWithScopes = new[] { "chat" }
};
var serializedBody = JsonConvert.SerializeObject(body);
var requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri)
{
Content = new StringContent(serializedBody, Encoding.UTF8, "application/json")
};
將 resourceEndpoint
取代為您的實際資源端點值。
建立內容雜湊
內容雜湊是 HMAC 簽章的一部分。 使用下列程式碼來計算內容雜湊。 您可以將此方法新增至 Main
方法底下的 Progam.cs
。
static string ComputeContentHash(string content)
{
using var sha256 = SHA256.Create();
byte[] hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(content));
return Convert.ToBase64String(hashedBytes);
}
計算簽章
使用下列程式代碼來建立計算 HMAC 簽章的方法。
static string ComputeSignature(string stringToSign)
{
string secret = "resourceAccessKey";
using var hmacsha256 = new HMACSHA256(Convert.FromBase64String(secret));
var bytes = Encoding.UTF8.GetBytes(stringToSign);
var hashedBytes = hmacsha256.ComputeHash(bytes);
return Convert.ToBase64String(hashedBytes);
}
將 resourceAccessKey
取代為您實際通訊服務資源的存取金鑰。
建立授權標頭字串
我們現在會建構要新增至授權標頭的字串。
- 準備要簽署標頭的值。
- 使用國際標準時間 (UTC) 時區指定目前的時間戳記。
- 取得要求授權單位 (DNS 主機名稱或 IP 位址和連接埠號碼)。
- 計算內容雜湊。
- 準備要簽署的字串。
- 計算簽章。
- 此將用於授權標頭中的字串串連。
將下列程式碼新增至 Main
方法。
// Specify the 'x-ms-date' header as the current UTC timestamp according to the RFC1123 standard
var date = DateTimeOffset.UtcNow.ToString("r", CultureInfo.InvariantCulture);
// Get the host name corresponding with the 'host' header.
var host = requestUri.Authority;
// Compute a content hash for the 'x-ms-content-sha256' header.
var contentHash = ComputeContentHash(serializedBody);
// Prepare a string to sign.
var stringToSign = $"POST\n{requestUri.PathAndQuery}\n{date};{host};{contentHash}";
// Compute the signature.
var signature = ComputeSignature(stringToSign);
// Concatenate the string, which will be used in the authorization header.
var authorizationHeader = $"HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature={signature}";
將標頭新增至 requestMessage
使用下列程式代碼,將必要的標頭新增至 requestMessage
。
// Add a date header.
requestMessage.Headers.Add("x-ms-date", date);
// Add a host header.
// In C#, the 'host' header is added automatically by the 'HttpClient'. However, this step may be required on other platforms such as Node.js.
// Add a content hash header.
requestMessage.Headers.Add("x-ms-content-sha256", contentHash);
// Add an authorization header.
requestMessage.Headers.Add("Authorization", authorizationHeader);
測試用戶端
使用 HttpClient
呼叫端點,並檢查回應。
HttpClient httpClient = new HttpClient
{
BaseAddress = requestUri
};
var response = await httpClient.SendAsync(requestMessage);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
必要條件
開始之前,請務必:
- 建立具有有效訂閱的 Azure 帳戶。 如需詳細資訊,請參閱免費建立帳戶。
- 下載並安裝 Python。
- 下載並安裝 Visual Studio Code 或其他支援 Python 的 IDE。
- 建立 Azure 通訊服務資源。 如需詳細資訊,請參閱建立 Azure 通訊服務資源。 在本教學課程中,您將需要 resource_endpoint_name 和 resource_endpoint_secret。
使用 Python 簽署 HTTP 要求
存取金鑰驗證會使用共用的秘密金鑰,為每個 HTTP 要求產生 HMAC 簽章。 此簽章是使用 SHA256 演算法所產生,並使用 HMAC-SHA256
配置在 Authorization
標頭中傳送。 例如:
Authorization: "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=<hmac-sha256-signature>"
hmac-sha256-signature
包含:
- HTTP 動詞指令 (例如
GET
或PUT
) - HTTP 要求路徑
- x-ms-date
- Host
- x-ms-content-sha256
設定
下列步驟說明如何建構授權標頭。
建立新的 Python 指令碼
開啟您選擇的 Visual Studio Code 或其他 IDE 或編輯器,並建立名為 sign_hmac_tutorial.py
的新檔案。 將此檔案儲存至已知的資料夾。
新增必要匯入
使用下列程式碼更新 sign_hmac_tutorial.py
指令碼以開始。
import base64
import hashlib
import hmac
import json
from datetime import datetime, timezone
from urllib import request
準備要求的資料
在此範例中,我們將使用通訊服務驗證 API (2021-03-07
版) 來簽署建立新身分識別的要求。
將下列程式碼新增至 sign_hmac_tutorial.py
指令碼。
- 將
resource_endpoint_name
取代為您的實際資源端點名稱值。 您可以在 Azure 通訊服務資源的 [概觀] 區段中找到這個值。 此為 "https://" 之後 "Endpoint" 的值。 - 將
resource_endpoint_secret
取代為您的實際資源端點祕密值。 您可以在 Azure 通訊服務資源的 [金鑰] 區段中找到這個值。 此為 "Key" 的值 - 主要或次要。
host = "resource_endpoint_name"
resource_endpoint = f"https://{host}"
path_and_query = "/identities?api-version=2021-03-07"
secret = "resource_endpoint_secret"
# Create a uri you are going to call.
request_uri = f"{resource_endpoint}{path_and_query}"
# Endpoint identities?api-version=2021-03-07 accepts list of scopes as a body.
body = { "createTokenWithScopes": ["chat"] }
serialized_body = json.dumps(body)
content = serialized_body.encode("utf-8")
建立內容雜湊
內容雜湊是 HMAC 簽章的一部分。 使用下列程式碼來計算內容雜湊。 您可以將此方法新增至 sign_hmac_tutorial.py
指令碼。
def compute_content_hash(content):
sha_256 = hashlib.sha256()
sha_256.update(content)
hashed_bytes = sha_256.digest()
base64_encoded_bytes = base64.b64encode(hashed_bytes)
content_hash = base64_encoded_bytes.decode('utf-8')
return content_hash
計算簽章
使用下列程式代碼來建立計算 HMAC 簽章的方法。
def compute_signature(string_to_sign, secret):
decoded_secret = base64.b64decode(secret)
encoded_string_to_sign = string_to_sign.encode('utf-8')
hashed_bytes = hmac.digest(decoded_secret, encoded_string_to_sign, digest=hashlib.sha256)
encoded_signature = base64.b64encode(hashed_bytes)
signature = encoded_signature.decode('utf-8')
return signature
根據 RFC1123 標準取得目前的 UTC 時間戳記
使用下列程式碼可取得與地區設定無關的所需日期格式。
def format_date(dt):
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
utc = dt.utctimetuple()
return "{}, {:02} {} {:04} {:02}:{:02}:{:02} GMT".format(
days[utc.tm_wday],
utc.tm_mday,
months[utc.tm_mon-1],
utc.tm_year,
utc.tm_hour,
utc.tm_min,
utc.tm_sec)
建立授權標頭字串
我們現在會建構要新增至授權標頭的字串。
- 準備要簽署標頭的值。
- 使用國際標準時間 (UTC) 時區指定目前的時間戳記。
- 取得要求授權單位 (DNS 主機名稱或 IP 位址和連接埠號碼)。
- 計算內容雜湊。
- 準備要簽署的字串。
- 計算簽章。
- 此將用於授權標頭中的字串串連。
將下列程式碼新增至 sign_hmac_tutorial.py
指令碼。
# Specify the 'x-ms-date' header as the current UTC timestamp according to the RFC1123 standard
utc_now = datetime.now(timezone.utc)
date = format_date(utc_now)
# Compute a content hash for the 'x-ms-content-sha256' header.
content_hash = compute_content_hash(content)
# Prepare a string to sign.
string_to_sign = f"POST\n{path_and_query}\n{date};{host};{content_hash}"
# Compute the signature.
signature = compute_signature(string_to_sign, secret)
# Concatenate the string, which will be used in the authorization header.
authorization_header = f"HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature={signature}"
新增標頭
使用下列程式代碼來新增必要的標頭。
request_headers = {}
# Add a date header.
request_headers["x-ms-date"] = date
# Add content hash header.
request_headers["x-ms-content-sha256"] = content_hash
# Add authorization header.
request_headers["Authorization"] = authorization_header
# Add content type header.
request_headers["Content-Type"] = "application/json"
測試用戶端
呼叫端點並檢查回應。
req = request.Request(request_uri, content, request_headers, method='POST')
with request.urlopen(req) as response:
response_string = json.load(response)
print(response_string)
清除資源
若要清除和移除通訊服務訂閱,請刪除資源或資源群組。 刪除資源群組也會刪除與其相關聯的任何其他資源。 您可以深入了解清除 Azure 通訊服務資源和清除 Azure Functions 資源。
下一步
您可能也想要: