Freigeben über


Signieren einer HTTP-Anforderung mithilfe von Hash-basierten Nachrichtenauthentifizierungscode (HMAC)

In diesem Artikel wird beschrieben, wie Sie eine HTTP-Anforderung mit einer Hash-basierten Nachrichtenauthentifizierungscodesignatur (HMAC) signieren.

Note

Es wird empfohlen, die Azure-SDKs zum Signieren einer HTTP-Anforderung zu verwenden. Der in diesem Artikel beschriebene Ansatz ist eine Fallbackoption, wenn Azure-SDKs aus irgendeinem Grund nicht verwendet werden können.

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen Sie eine Anforderungsnachricht.
  • Erstellen eines Inhaltshash
  • Berechnen einer Signatur.
  • Erstellen einer Autorisierungsheader-Zeichenfolge
  • Fügen Sie Kopfzeilen hinzu.

Prerequisites

Signieren einer HTTP-Anforderung mit C#

Bei der Authentifizierung per Zugriffsschlüssel wird ein gemeinsamer geheimer Schlüssel verwendet, um eine HMAC-Signatur für jede HTTP-Anforderung zu generieren. Diese Signatur wird mit dem SHA256-Algorithmus generiert und im Header Authorization unter Verwendung des Schemas HMAC-SHA256 gesendet. Beispiel:

Authorization: "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=<hmac-sha256-signature>"

hmac-sha256-signature umfasst Folgendes:

  • HTTP-Verb (z. B. GET oder PUT)
  • HTTP-Anforderungspfad
  • x-ms-date
  • Host
  • x-ms-content-sha256

Einrichten des Autorisierungsheaders

Führen Sie die folgenden Schritte aus, um den Autorisierungsheader zu erstellen.

Erstellen einer neuen C#-Anwendung

Verwenden Sie in einem Konsolenfenster (z. B. cmd, PowerShell oder Bash) den Befehl dotnet new zum Erstellen einer neuen Konsolen-App mit dem Namen SignHmacTutorial. Dieser Befehl erstellt ein einfaches „Hallo Welt“-C#-Projekt mit einer einzigen Quelldatei: Program.cs.

dotnet new console -o SignHmacTutorial

Wechseln Sie zum Ordner der neu erstellten App. Verwenden Sie den dotnet build Befehl, um Die Anwendung zu kompilieren.

cd SignHmacTutorial
dotnet build

Installieren des Pakets

Installieren Sie das Paket Newtonsoft.Json für die Textserialisierung.

dotnet add package Newtonsoft.Json

Aktualisieren Sie die Deklaration der Methode Main, sodass asynchroner Code unterstützt wird. Verwenden Sie zum Einstieg den folgenden Code:

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.
        }
    }
}

Erstellen einer Anforderungsnachricht

In diesem Beispiel signieren Sie eine Anforderung zum Erstellen einer neuen Identität mithilfe der Communication Services Authentication API (Version 2021-03-07).

Fügen Sie der Main -Methode den folgenden Code hinzu.

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")
};

Ersetzen Sie resourceEndpoint durch den Wert Ihres tatsächlichen Ressourcenendpunkts.

Inhaltshash erstellen

Der Inhaltshash ist Teil Ihrer HMAC-Signatur. Verwenden Sie den folgenden Code, um den Inhaltshash zu berechnen. Diese Methode können Sie unter der Methode Program.cs zu Main hinzufügen:

static string ComputeContentHash(string content)
{
    using var sha256 = SHA256.Create();
    byte[] hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(content));
    return Convert.ToBase64String(hashedBytes);
}

Berechnen einer Signatur

Verwenden Sie den folgenden Code, um eine Methode zum Berechnen der HMAC-Signatur zu erstellen.

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);
}

Ersetzen Sie resourceAccessKey durch den Zugriffsschlüssel Ihrer tatsächlichen Communication Services-Ressource.

Erstellen einer Autorisierungs-Header-Zeichenfolge

Jetzt erstellen Sie die Zeichenfolge, die Sie zu Ihrem Autorisierungsheader hinzufügen.

  1. Bereiten Sie Werte für die zu signierenden Header vor.
    1. Geben Sie den aktuellen Zeitstempel mithilfe der Utc-Zeitzone (Coordinated Universal Time) an.
    2. Rufen Sie die Anforderungsautorisierung ab. Verwenden Sie den DNS-Hostnamen (Domain Name System) oder die IP-Adresse und die Portnummer.
    3. Berechnen Sie einen Inhaltshash.
  2. Bereiten Sie eine Zeichenfolge für die Signierung vor.
  3. Berechnen Sie die Signatur.
  4. Verketten Sie die Zeichenfolge, die im Autorisierungsheader verwendet wird.

Fügen Sie der Main -Methode den folgenden Code hinzu.

// 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}";

Hinzufügen von Headern zu „requestMessage“

Verwenden Sie den folgenden Code, um die erforderlichen Header zu Ihrem requestMessage Parameter hinzuzufügen.

// 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);

Testen des Clients

Rufen Sie den Endpunkt mithilfe von HttpClient auf, und überprüfen Sie die Antwort.

HttpClient httpClient = new HttpClient
{
    BaseAddress = requestUri
};
var response = await httpClient.SendAsync(requestMessage);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);

Prerequisites

  • Erstellen Sie ein Azure-Konto mit einem aktiven Abonnement. Wenn Sie kein Azure-Abonnement haben, sehen Sie sich Erstellen Sie ein kostenloses Konto an.
  • Laden Sie Python herunter, und installieren Sie die Programmiersprache.
  • Laden Sie Visual Studio Code oder eine andere integrierte Entwicklungsumgebung (IDE) herunter, die Python unterstützt, und installieren Sie sie.
  • Erstellen Sie eine Azure Communication Services-Ressource. Wenn Sie nicht über eine Ressource verfügen, sehen Sie unter Erstellen einer Ressource für Kommunikationsdienste nach. Für dieses Beispiel benötigen Sie Ihre resource_endpoint_name und resource_endpoint_secret Parameter.

Signieren einer HTTP-Anforderung mit Python

Bei der Authentifizierung per Zugriffsschlüssel wird ein gemeinsamer geheimer Schlüssel verwendet, um eine HMAC-Signatur für jede HTTP-Anforderung zu generieren. Diese Signatur wird mit dem SHA256-Algorithmus generiert und im Header Authorization unter Verwendung des Schemas HMAC-SHA256 gesendet. Beispiel:

Authorization: "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=<hmac-sha256-signature>"

hmac-sha256-signature umfasst Folgendes:

  • HTTP-Verb (z. B. GET oder PUT)
  • HTTP-Anforderungspfad
  • x-ms-date
  • Host
  • x-ms-content-sha256

Einrichten des Autorisierungsheaders

Führen Sie die folgenden Schritte aus, um den Autorisierungsheader zu erstellen.

Ein neues Python-Skript erstellen

Öffnen Sie Visual Studio Code oder eine andere IDE oder einen anderen Editor Ihrer Wahl. Erstelle eine neue Datei mit dem Namen sign_hmac_tutorial.py. Speichern Sie diese Datei in einem bekannten Ordner.

Hinzufügen der erforderlichen Importe

Aktualisieren Sie das Skript sign_hmac_tutorial.py mit dem folgenden Code, um zu beginnen.

import base64
import hashlib
import hmac
import json
from datetime import datetime, timezone
from urllib import request

Aufbereiten von Daten für die Anforderung

In diesem Beispiel signieren Sie eine Anforderung zum Erstellen einer neuen Identität mithilfe der Kommunikationsdienste-Authentifizierungs-API (Version2021-03-07).

Fügen Sie dem Skript sign_hmac_tutorial.py den folgenden Code hinzu.

  • Ersetzen Sie resource_endpoint_name durch den Namenswert Ihres tatsächlichen Ressourcenendpunkts. Sie finden diesen Wert im Abschnitt "Übersicht" Ihrer Kommunikationsdienste-Ressource. Dies ist der Wert von Endpoint nach https://.
  • Ersetzen Sie resource_endpoint_secret durch den Geheimniswert Ihres tatsächlichen Ressourcenendpunkts. Sie finden diesen Wert im Abschnitt "Schlüssel " Ihrer Kommunikationsdienste-Ressource. Es ist der Wert von Key, der entweder primär oder sekundär ist.
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 the list of scopes as a body.
body = { "createTokenWithScopes": ["chat"] }

serialized_body = json.dumps(body)
content = serialized_body.encode("utf-8")

Inhaltshash erstellen

Der Inhaltshash ist Teil Ihrer HMAC-Signatur. Verwenden Sie den folgenden Code, um den Inhaltshash zu berechnen. Sie können diese Methode dem sign_hmac_tutorial.py Skript hinzufügen.

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

Berechnen einer Signatur

Verwenden Sie den folgenden Code, um eine Methode zum Berechnen der HMAC-Signatur zu erstellen.

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

Abrufen eines aktuellen UTC-Zeitstempels gemäß dem RFC1123 Standard

Verwenden Sie den folgenden Code, um das Datumsformat abzurufen, das unabhängig von Gebietsschemaeinstellungen sein soll.

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)

Erstellen einer Autorisierungs-Header-Zeichenfolge

Jetzt erstellen Sie die Zeichenfolge, die Sie zu Ihrem Autorisierungsheader hinzufügen.

  1. Bereiten Sie Werte für die zu signierenden Header vor.
    1. Geben Sie den aktuellen Zeitstempel mithilfe der Utc-Zeitzone (Coordinated Universal Time) an.
    2. Rufen Sie die Anforderungsautorisierung ab. Verwenden Sie den DNS-Hostnamen (Domain Name System) oder die IP-Adresse und die Portnummer.
    3. Berechnen Sie einen Inhaltshash.
  2. Bereiten Sie eine Zeichenfolge für die Signierung vor.
  3. Berechnen Sie die Signatur.
  4. Verketten Sie die Zeichenfolge, die im Autorisierungsheader verwendet wird.

Fügen Sie dem Skript sign_hmac_tutorial.py den folgenden Code hinzu.

# 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}"

Hinzufügen von Headern

Verwenden Sie den folgenden Code, um die erforderlichen Header hinzuzufügen.

request_headers = {}

# Add a date header.
request_headers["x-ms-date"] = date

# Add a content hash header.
request_headers["x-ms-content-sha256"] = content_hash

# Add an authorization header.
request_headers["Authorization"] = authorization_header

# Add a content type header.
request_headers["Content-Type"] = "application/json"

Testen des Clients

Rufen Sie den Endpunkt auf, und überprüfen Sie die Antwort.

req = request.Request(request_uri, content, request_headers, method='POST')
with request.urlopen(req) as response:
  response_string = json.load(response)
print(response_string)

Bereinigen von Ressourcen

Wenn Sie ein Communication Services-Abonnement bereinigen und entfernen möchten, löschen Sie die Ressource oder Ressourcengruppe. Wenn Sie die Ressourcengruppe löschen, werden auch alle anderen Ressourcen gelöscht, die ihr zugeordnet sind. Weitere Informationen zum Bereinigen von Azure Communication Services-Ressourcen und zum Bereinigen von Azure Functions-Ressourcen finden Sie hier.