Sdílet prostřednictvím


Podepsání požadavku HTTP pomocí ověřovacího kódu založeného na hodnotě hash (HMAC)

Tento článek popisuje, jak podepsat požadavek HTTP s podpisem HMAC (hash-based message authentication code).

Note

K podepsání požadavku HTTP doporučujeme použít sady Azure SDK . Přístup popsaný v tomto článku je záložní možností, pokud se sady Azure SDK z nějakého důvodu nedají použít.

V tomto kurzu se naučíte:

  • Vytvořte žádost.
  • Vytvořte hashovací obsah.
  • Vypočítat podpis.
  • Vytvořte řetězec autorizační hlavičky.
  • Přidejte záhlaví.

Prerequisites

Podepište požadavek HTTP pomocí C#

Ověřování pomocí přístupového klíče používá sdílený tajný klíč k vytvoření HMAC podpisu pro každý HTTP požadavek. Tato podpisová značka je generována pomocí algoritmu SHA256 a je zaslána v záhlaví Authorization pomocí schématu HMAC-SHA256. Například:

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

Skládá se z: hmac-sha256-signature

  • HTTP sloveso (například GET nebo PUT)
  • HTTP cesta žádosti
  • x-ms-date
  • Host
  • x-ms-content-sha256

Nastavte autorizační hlavičku

Provedením následujících kroků vytvořte autorizační hlavičku.

Vytvořte novou aplikaci v jazyce C#

V okně konzole, například cmd, PowerShell nebo Bash, použijte příkaz dotnet new k vytvoření nové konzolové aplikace s názvem SignHmacTutorial. Tento příkaz vytvoří jednoduchý projekt "Hello World" C# s jedním zdrojovým souborem: Program.cs.

dotnet new console -o SignHmacTutorial

Změňte svůj adresář na nově vytvořenou složku aplikace. Ke kompilaci aplikace použijte dotnet build příkaz.

cd SignHmacTutorial
dotnet build

Nainstalujte balíček

Nainstalujte balíček Newtonsoft.Json, který se používá pro serializaci těla.

dotnet add package Newtonsoft.Json

Aktualizujte deklaraci metody Main, aby podporovala asynchronní kód. Použijte následující kód pro zahájení.

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

Vytvořte žádost o zprávu

Pro tento příklad podepíšete žádost o vytvoření nové identity pomocí API pro ověřování komunikačních služeb (verze 2021-03-07).

Přidejte následující kód 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")
};

Nahraďte resourceEndpoint hodnotou skutečného koncového bodu zdroje.

Vytvořte hash obsahu

Hash obsahu je součástí vaší HMAC podpisu. Použijte následující kód ke spočítání hashe obsahu. Tuto metodu můžete přidat do Program.cs pod metodou Main.

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

Vypočítat podpis

Použijte následující kód k vytvoření metody pro výpočet vaší HMAC podpisu.

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

Nahraďte resourceAccessKey přístupovým klíčem vaší skutečné služby Communication Services.

Vytvořte řetězec záhlaví autorizace

Nyní vytvoříte řetězec, který přidáte do své autorizační hlavičky.

  1. Připravte hodnoty pro hlavičky, které mají být podepsány.
    1. Určete aktuální časové razítko pomocí časového pásma koordinovaného světového času (UTC).
    2. Získejte oprávnění ke žádosti. Použijte název hostitele systému doménových jmen (DNS) nebo IP adresu a číslo portu.
    3. Vypočítejte hash obsahu.
  2. Připravte řetězec k podpisu.
  3. Vypočítat podpis.
  4. Spojte řetězec, který se používá v autorizační hlavičce.

Přidejte následující kód 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}";

Přidejte hlavičky k požadavku message

Použijte následující kód k přidání požadovaných hlaviček k vašemu parametru 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);

Testujte klienta

Zavolejte koncový bod pomocí HttpClient a zkontrolujte odpověď.

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

Prerequisites

  • Vytvořte účet Azure s aktivním předplatným. Pokud nemáte předplatné Azure, podívejte se na Vytvořit si účet zdarma.
  • Stáhněte a nainstalujte Python .
  • Stáhněte a nainstalujte Visual Studio Code nebo jiné integrované vývojové prostředí (IDE), které podporuje Python.
  • Vytvořte prostředek Azure Communication Services. Pokud nemáte prostředek, viz Vytvoření prostředku komunikačních služeb. K tomuto příkladu potřebujete vaše parametry resource_endpoint_name a resource_endpoint_secret.

Podepište HTTP požadavek pomocí Pythonu

Ověřování pomocí přístupového klíče používá sdílený tajný klíč k vytvoření HMAC podpisu pro každý HTTP požadavek. Tato podpisová značka je generována pomocí algoritmu SHA256 a je zaslána v záhlaví Authorization pomocí schématu HMAC-SHA256. Například:

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

Skládá se z: hmac-sha256-signature

  • HTTP sloveso (například GET nebo PUT)
  • HTTP cesta žádosti
  • x-ms-date
  • Host
  • x-ms-content-sha256

Nastavte autorizační hlavičku

Provedením následujících kroků vytvořte autorizační hlavičku.

Vytvořte nový skript v Pythonu

Otevřete Visual Studio Code nebo jinou IDE či editor podle svého výběru. Vytvořte nový soubor s názvem sign_hmac_tutorial.py. Uložte tento soubor do známé složky.

Přidejte potřebné importy

Upravte skript sign_hmac_tutorial.py následujícím kódem pro začátek.

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

Připravte data pro požadavek

Pro tento příklad podepisujete požadavek na vytvoření nové identity pomocí API pro ověření komunikačních služeb (verze 2021-03-07).

Přidejte následující kód do sign_hmac_tutorial.py skriptu.

  • Nahraďte resource_endpoint_name skutečným názvem koncového bodu zdroje. Tuto hodnotu najdete v části Přehled u vašeho zdroje pro komunikační služby. Je to hodnota Endpoint po https://.
  • Nahraďte resource_endpoint_secret skutečnou hodnotou tajného klíče koncového bodu zdroje. Tuto hodnotu najdete v sekci Keys vašeho zdroje komunikačních služeb. Je to hodnota Key, která je buď primární nebo sekundární.
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")

Vytvořte hash obsahu

Hash obsahu je součástí vaší HMAC podpisu. Použijte následující kód ke spočítání hashe obsahu. Můžete přidat tuto metodu do skriptu 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

Vypočítat podpis

Použijte následující kód k vytvoření metody pro výpočet vaší HMAC podpisu.

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

Získejte aktuální UTC časové razítko podle standardu RFC1123.

Použijte následující kód k získání formátu data, který potřebujete, nezávisle na nastavení místního prostředí.

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)

Vytvořte řetězec záhlaví autorizace

Nyní vytvoříte řetězec, který přidáte do své autorizační hlavičky.

  1. Připravte hodnoty pro hlavičky, které mají být podepsány.
    1. Určete aktuální časové razítko pomocí časového pásma koordinovaného světového času (UTC).
    2. Získejte oprávnění ke žádosti. Použijte název hostitele systému doménových jmen (DNS) nebo IP adresu a číslo portu.
    3. Vypočítejte hash obsahu.
  2. Připravte řetězec k podpisu.
  3. Vypočítat podpis.
  4. Spojte řetězec, který se používá v autorizační hlavičce.

Přidejte následující kód do sign_hmac_tutorial.py skriptu.

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

Přidejte hlavičky

Použijte následující kód pro přidání požadovaných záhlaví.

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"

Testujte klienta

Zavolejte koncový bod a zkontrolujte odpověď.

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

Vyčistit zdroje

Chcete-li vyčistit a odstranit předplatné služby Communication Services, odstraňte zdroj nebo skupinu zdrojů. Odstranění skupiny prostředků také odstraní všechny ostatní prostředky s ní spojené. Zjistíte více informací o tom, jak vyčistit zdroje Azure Communication Services a vyčistit zdroje Azure Functions.