Freigeben über


Signieren einer HTTP-Anforderung

In diesem Tutorial erfahren Sie, wie Sie eine HTTP-Anforderung mit einer HMAC-Signatur signieren.

Hinweis

Es wird dringend empfohlen, Azure SDKs zu verwenden. Bei dem hier beschriebenen Ansatz handelt es sich um eine Fallbackoption für den Fall, dass Azure SDKs nicht verwendet werden können.

Voraussetzungen

Führen Sie die folgenden Schritte aus, bevor Sie beginnen:

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

In den folgenden Schritten wird beschrieben, wie Sie den Autorisierungsheader 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 Befehl dotnet build, 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 wird eine Anforderung zum Erstellen einer neuen Identität mithilfe der Authentifizierungs-API (Version 2021-03-07) von Communication Services signiert.

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.

Erstellen eines Inhaltshashs

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 Main zu Progam.cs 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 Autorisierungsheader-Zeichenfolge

In diesem Abschnitt wird die Zeichenfolge erstellt, die Sie später unserem Autorisierungsheader hinzufügen.

  1. Bereiten Sie Werte für die zu signierenden Header vor.
    1. Geben Sie den aktuellen Zeitstempel in der Zeitzone UTC (Koordinierte Weltzeit) an.
    2. Rufen Sie die Anforderungsstelle (DNS-Hostname oder IP-Adresse und Portnummer) ab.
    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 für den Autorisierungsheader.

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 Ihrer Anforderungsnachricht (requestMessage) die erforderlichen Header 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);

Voraussetzungen

Führen Sie die folgenden Schritte aus, bevor Sie beginnen:

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

In den folgenden Schritten wird beschrieben, wie Sie den Autorisierungsheader erstellen:

Erstellen eines Python-Skripts

Öffnen Sie Visual Studio Code, eine andere IDE oder einen Editor Ihrer Wahl, und erstellen Sie eine neue Datei namens 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 wird eine Anforderung zum Erstellen einer neuen Identität mithilfe der Authentifizierungs-API (Version 2021-03-07) von Communication Services signiert.

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. Diesen Wert finden Sie im Abschnitt „Übersicht“ Ihrer Azure Communication Services-Ressource. Es ist der Wert von „Endpunkt“ nach „https://“.
  • Ersetzen Sie resource_endpoint_secret durch den Geheimniswert Ihres tatsächlichen Ressourcenendpunkts. Diesen Wert finden Sie im Abschnitt „Schlüssel“ Ihrer Azure Communication Services-Ressource. Es ist der Wert von „Schlüssel“ – entweder primär oder sekundär.
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")

Erstellen eines Inhaltshashs

Der Inhaltshash ist Teil Ihrer HMAC-Signatur. Verwenden Sie den folgenden Code, um den Inhaltshash zu berechnen. Sie können diese Methode zum Skript sign_hmac_tutorial.py 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 des aktuellen UTC-Zeitstempels gemäß dem RFC1123-Standard

Verwenden Sie den folgenden Code zum Abrufen des gewünschten Datumsformat unabhängig von den Gebietsschemaeinstellungen.

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 Autorisierungsheader-Zeichenfolge

In diesem Abschnitt wird die Zeichenfolge erstellt, die Sie später unserem Autorisierungsheader hinzufügen.

  1. Bereiten Sie Werte für die zu signierenden Header vor.
    1. Geben Sie den aktuellen Zeitstempel in der Zeitzone UTC (Koordinierte Weltzeit) an.
    2. Rufen Sie die Anforderungsstelle (DNS-Hostname oder IP-Adresse und Portnummer) ab.
    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 für den Autorisierungsheader.

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

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. Hier finden Sie weitere Informationen zum Bereinigen von Azure Communication Service-Ressourcen und zum Bereinigen von Azure Functions-Ressourcen.

Nächste Schritte

Weitere Möglichkeiten: