Podpisywanie żądania HTTP

Z tego samouczka dowiesz się, jak podpisać żądanie HTTP przy użyciu podpisu HMAC.

Uwaga

Zdecydowanie zachęcamy do korzystania z zestawów SDK platformy Azure. Metoda opisana w tym miejscu jest opcją rezerwową dla przypadków, gdy zestawy SDK platformy Azure nie mogą być używane z jakiegokolwiek powodu.

Wymagania wstępne

Przed rozpoczęciem upewnij się, że:

Podpisywanie żądania HTTP przy użyciu języka C #

Uwierzytelnianie klucza dostępu używa wspólnego klucza tajnego do generowania podpisu HMAC dla każdego żądania HTTP. Ten podpis jest generowany przy użyciu algorytmu SHA256 i jest wysyłany w nagłówku Authorization przy użyciu schematu HMAC-SHA256 . Przykład:

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

Składa hmac-sha256-signature się z:

  • Czasownik HTTP (na przykład GET lub PUT)
  • Ścieżka żądania HTTP
  • x-ms-date
  • Host
  • x-ms-content-sha256

Konfigurowanie

W poniższych krokach opisano sposób konstruowania nagłówka autoryzacji.

Tworzenie nowej aplikacji w języku C#

W oknie konsoli, takim jak cmd, PowerShell lub Bash, użyj dotnet new polecenia , aby utworzyć nową aplikację konsolową o nazwie SignHmacTutorial. To polecenie tworzy prosty projekt języka C# "Hello world" z jednym plikiem źródłowym: Program.cs.

dotnet new console -o SignHmacTutorial

Zmień katalog na nowo utworzony folder aplikacji. dotnet build Użyj polecenia , aby skompilować aplikację.

cd SignHmacTutorial
dotnet build

Instalowanie pakietu

Zainstaluj pakiet Newtonsoft.Json używany do serializacji treści.

dotnet add package Newtonsoft.Json

Zaktualizuj deklarację Main metody, aby obsługiwać kod asynchroniczny. Użyj następującego kodu, aby rozpocząć.

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

Tworzenie komunikatu żądania

W tym przykładzie podpiszemy żądanie utworzenia nowej tożsamości przy użyciu interfejsu API uwierzytelniania usług komunikacyjnych (wersja 2021-03-07).

Dodaj następujący kod do metody 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")
};

Zastąp resourceEndpoint wartość rzeczywistego punktu końcowego zasobu.

Tworzenie skrótu zawartości

Skrót zawartości jest częścią podpisu HMAC. Użyj następującego kodu, aby obliczyć skrót zawartości. Tę metodę można dodać do Progam.cs metody w ramach Main metody .

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

Obliczanie podpisu

Użyj poniższego kodu, aby utworzyć metodę przetwarzania podpisu 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);
}

Zastąp resourceAccessKey element kluczem dostępu rzeczywistego zasobu usług komunikacyjnych.

Tworzenie ciągu nagłówka autoryzacji

Teraz skonstruujemy ciąg, który dodamy do nagłówka autoryzacji.

  1. Przygotuj wartości nagłówków do podpisania.
    1. Określ bieżącą sygnaturę czasową przy użyciu strefy czasowej uniwersalnej koordynowanej (UTC).
    2. Pobierz urząd żądania (nazwa hosta DNS lub adres IP i numer portu).
    3. Oblicz skrót zawartości.
  2. Przygotuj ciąg do podpisania.
  3. Oblicz podpis.
  4. Połącz ciąg, który będzie używany w nagłówku autoryzacji.

Dodaj następujący kod do metody 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}";

Dodawanie nagłówków do elementu requestMessage

Użyj następującego kodu, aby dodać wymagane nagłówki do pliku 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);

Testowanie klienta

Wywołaj punkt końcowy przy użyciu polecenia HttpClienti sprawdź odpowiedź.

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

Wymagania wstępne

Przed rozpoczęciem upewnij się, że:

  • Utwórz konto platformy Azure z aktywną subskrypcją. Aby uzyskać szczegółowe informacje, zobacz Tworzenie konta bezpłatnie.
  • Pobierz i zainstaluj język Python.
  • Pobierz i zainstaluj Visual Studio Code lub inne środowisko IDE, które obsługuje język Python.
  • Utwórz zasób Azure Communication Services. Aby uzyskać szczegółowe informacje, zobacz Tworzenie zasobu Azure Communication Services. Do tego samouczka będziesz potrzebować resource_endpoint_name i resource_endpoint_secret .

Podpisywanie żądania HTTP przy użyciu języka Python

Uwierzytelnianie klucza dostępu używa wspólnego klucza tajnego do generowania podpisu HMAC dla każdego żądania HTTP. Ten podpis jest generowany przy użyciu algorytmu SHA256 i jest wysyłany w nagłówku Authorization przy użyciu schematu HMAC-SHA256 . Przykład:

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

Składa hmac-sha256-signature się z:

  • Czasownik HTTP (na przykład GET lub PUT)
  • Ścieżka żądania HTTP
  • x-ms-date
  • Host
  • x-ms-content-sha256

Konfigurowanie

W poniższych krokach opisano sposób konstruowania nagłówka autoryzacji.

Tworzenie nowego skryptu języka Python

Otwórz wybrane Visual Studio Code lub innego środowiska IDE lub edytora i utwórz nowy plik o nazwie sign_hmac_tutorial.py. Zapisz ten plik w znanym folderze.

Dodawanie niezbędnych importów

Zaktualizuj skrypt przy sign_hmac_tutorial.py użyciu następującego kodu, aby rozpocząć.

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

Przygotowywanie danych do żądania

W tym przykładzie podpiszemy żądanie utworzenia nowej tożsamości przy użyciu interfejsu API uwierzytelniania usług komunikacyjnych (wersja 2021-03-07).

Dodaj następujący kod do skryptu sign_hmac_tutorial.py .

  • Zastąp resource_endpoint_name wartość rzeczywistą nazwą punktu końcowego zasobu. Tę wartość można znaleźć w sekcji Przegląd zasobu Azure Communication Services. Jest to wartość "Endpoint" po "https://".
  • Zastąp resource_endpoint_secret element wartością wpisu tajnego rzeczywistego punktu końcowego zasobu. Tę wartość można znaleźć w sekcji Klucze zasobu Azure Communication Services. Jest to wartość "Klucz" — podstawowa lub pomocnicza.
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")

Tworzenie skrótu zawartości

Skrót zawartości jest częścią podpisu HMAC. Użyj następującego kodu, aby obliczyć skrót zawartości. Tę metodę można dodać do sign_hmac_tutorial.py skryptu.

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

Obliczanie podpisu

Użyj poniższego kodu, aby utworzyć metodę przetwarzania podpisu 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

Pobierz bieżący znacznik czasu UTC zgodnie ze standardem RFC1123

Użyj następującego kodu, aby uzyskać żądany format daty niezależnie od ustawień regionalnych.

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)

Tworzenie ciągu nagłówka autoryzacji

Teraz skonstruujemy ciąg, który dodamy do nagłówka autoryzacji.

  1. Przygotuj wartości nagłówków do podpisania.
    1. Określ bieżącą sygnaturę czasową przy użyciu strefy czasowej uniwersalnej koordynowanej (UTC).
    2. Pobierz urząd żądania (nazwa hosta DNS lub adres IP i numer portu).
    3. Oblicz skrót zawartości.
  2. Przygotuj ciąg do podpisania.
  3. Oblicz podpis.
  4. Połącz ciąg, który będzie używany w nagłówku autoryzacji.

Dodaj następujący kod do skryptu 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}"

Dodawanie nagłówków

Użyj następującego kodu, aby dodać wymagane nagłówki.

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"

Testowanie klienta

Wywołaj punkt końcowy i sprawdź odpowiedź.

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

Czyszczenie zasobów

Aby wyczyścić i usunąć subskrypcję usług Communication Services, usuń zasób lub grupę zasobów. Usunięcie grupy zasobów powoduje również usunięcie wszystkich innych skojarzonych z nią zasobów. Więcej informacji na temat czyszczenia zasobów Azure Communication Services i czyszczenia zasobów Azure Functions.

Następne kroki

Możesz również chcieć: