Bagikan melalui


Menandatangani permintaan HTTP menggunakan kode autentikasi pesan berbasis hash (HMAC)

Artikel ini menjelaskan cara menandatangani permintaan HTTP dengan tanda tangan kode autentikasi pesan berbasis hash (HMAC).

Note

Sebaiknya gunakan Azure SDK untuk menandatangani permintaan HTTP. Pendekatan yang dijelaskan dalam artikel ini adalah opsi fallback jika Azure SDK tidak dapat digunakan karena alasan apa pun.

Dalam tutorial ini, Anda mempelajari cara:

  • Buat pesan permintaan.
  • Buat hash konten.
  • Menghitung tanda tangan.
  • Buatlah string untuk header otorisasi.
  • Tambahkan header.

Prerequisites

Menandatangani permintaan HTTP dengan C#

Autentikasi kunci akses menggunakan kunci rahasia bersama untuk menghasilkan tanda tangan HMAC pada setiap permintaan HTTP. Tanda tangan ini dihasilkan dengan algoritma SHA256 dan dikirim di header Authorization dengan menggunakan skema HMAC-SHA256. Contohnya:

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

hmac-sha256-signature terdiri dari:

  • Kata kerja HTTP (misalnya, GET atau PUT)
  • Jalur permintaan
  • x-ms-date
  • Host
  • x-ms-content-sha256

Menyiapkan header otorisasi

Selesaikan langkah-langkah berikut untuk membuat header otorisasi.

Membuat aplikasi C# baru

Di jendela konsol, seperti cmd, PowerShell, atau Azure CLI, gunakan perintah dotnet new untuk membuat aplikasi konsol baru bernama SignHmacTutorial. Perintah ini membuat proyek C# "Halo Dunia" sederhana dengan satu file sumber: Program.cs.

dotnet new console -o SignHmacTutorial

Ubah direktori Anda ke folder aplikasi yang baru dibuat. Untuk mengkompilasi aplikasi Anda, gunakan dotnet build perintah .

cd SignHmacTutorial
dotnet build

Pasang paket

Pasang paket Newtonsoft.Json yang digunakan untuk serialisasi tubuh.

dotnet add package Newtonsoft.Json

Perbarui deklarasi metode Main untuk mendukung kode asinkron. Gunakan kode berikut untuk memulai.

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

Membuat pesan permintaan

Untuk contoh ini, Anda menandatangani permintaan untuk membuat identitas baru dengan menggunakan COMMUNICATION Services Authentication API (versi 2021-03-07).

Tambahkan kode berikut ke metode 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")
};

Ganti resourceEndpoint dengan nilai titik akhir sumber daya Anda yang sebenarnya.

Membuat hash konten

Hash konten adalah bagian dari tanda tangan HMAC Anda. Gunakan kode berikut untuk menghitung hash konten. Anda dapat menambahkan metode ini ke Program.cs di metode Main.

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

Menghitung tanda tangan digital

Gunakan kode berikut untuk membuat metode menghasilkan tanda tangan HMAC Anda.

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

Ganti resourceAccessKey dengan kunci akses sumber daya Communication Services Anda yang sebenarnya.

Membuat untai (karakter) header otorisasi

Sekarang Anda membuat string yang Anda tambahkan pada header otorisasi Anda.

  1. Siapkan nilai header yang akan ditandatangani.
    1. Tentukan tanda waktu saat ini dengan menggunakan zona waktu Waktu Universal Terkoordinasi (UTC).
    2. Dapatkan otorisasi permintaan. Gunakan nama host atau alamat IP Sistem Nama Domain (DNS) dan nomor port.
    3. Hitung hash konten.
  2. Siapkan string untuk tanda tangan.
  3. Hitung tanda tangan.
  4. Menggabungkan string, yang digunakan di header otorisasi.

Tambahkan kode berikut ke metode 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}";

Tambahkan header ke requestMessage

Gunakan kode berikut untuk menambahkan header yang diperlukan ke parameter Anda 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);

Menguji klien

Hubungi titik akhir dengan menggunakan HttpClient, dan periksa responsnya.

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

Prerequisites

  • Buat akun Azure dengan langganan aktif. Jika Anda tidak memiliki langganan Azure, lihat Membuat akun secara gratis.
  • Unduh dan instal Python.
  • Unduh dan instal Visual Studio Code atau lingkungan pengembangan terintegrasi (IDE) lain yang mendukung Python.
  • Buat sumber daya Azure Communication Services. Jika Anda tidak memiliki sumber daya, baca Cara Membuat Sumber Daya Communication Services. Anda membutuhkan parameter resource_endpoint_name dan resource_endpoint_secret untuk contoh ini.

Menandatangani permintaan HTTP dengan Python

Autentikasi kunci akses menggunakan kunci rahasia bersama untuk menghasilkan tanda tangan HMAC pada setiap permintaan HTTP. Tanda tangan ini dihasilkan dengan algoritma SHA256 dan dikirim di header Authorization dengan menggunakan skema HMAC-SHA256. Contohnya:

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

hmac-sha256-signature terdiri dari:

  • Kata kerja HTTP (misalnya, GET atau PUT)
  • Jalur permintaan
  • x-ms-date
  • Host
  • x-ms-content-sha256

Menyiapkan header otorisasi

Selesaikan langkah-langkah berikut untuk membuat header otorisasi.

Membuat skrip Python baru

Buka Visual Studio Code atau IDE atau editor pilihan Anda lainnya. Buat file baru bernama sign_hmac_tutorial.py. Simpan file ini ke folder yang diketahui.

Menambahkan impor yang diperlukan

sign_hmac_tutorial.py Perbarui skrip dengan kode berikut untuk memulai.

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

Menyiapkan data untuk permintaan

Untuk contoh ini, Anda menandatangani permintaan untuk membuat identitas baru dengan menggunakan COMMUNICATION Services Authentication API (versi 2021-03-07).

Tambahkan kode berikut ke sign_hmac_tutorial.py skrip.

  • Ganti resource_endpoint_name dengan nilai nama titik akhir sumber daya nyata Anda. Anda dapat menemukan nilai ini di bagian Gambaran Umum sumber daya Communication Services Anda. Ini adalah nilai Endpoint setelah https://.
  • Ganti resource_endpoint_secret dengan nilai rahasia titik akhir sumber daya nyata Anda. Anda dapat menemukan nilai ini di bagian Kunci sumber daya Communication Services Anda. Ini adalah nilai Kunci, yang merupakan primer atau sekunder.
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")

Membuat hash konten

Hash konten adalah bagian dari tanda tangan HMAC Anda. Gunakan kode berikut untuk menghitung hash konten. Anda dapat menambahkan metode ini ke sign_hmac_tutorial.py skrip.

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

Menghitung tanda tangan digital

Gunakan kode berikut untuk membuat metode menghasilkan tanda tangan HMAC Anda.

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

Dapatkan tanda waktu UTC saat ini sesuai dengan standar RFC1123

Gunakan kode berikut untuk mendapatkan format tanggal yang Anda inginkan yang independen dari pengaturan lokal.

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)

Membuat untai (karakter) header otorisasi

Sekarang Anda membuat string yang Anda tambahkan pada header otorisasi Anda.

  1. Siapkan nilai header yang akan ditandatangani.
    1. Tentukan tanda waktu saat ini dengan menggunakan zona waktu Waktu Universal Terkoordinasi (UTC).
    2. Dapatkan otorisasi permintaan. Gunakan nama host atau alamat IP Sistem Nama Domain (DNS) dan nomor port.
    3. Hitung hash konten.
  2. Siapkan string untuk tanda tangan.
  3. Hitung tanda tangan.
  4. Menggabungkan string, yang digunakan di header otorisasi.

Tambahkan kode berikut ke sign_hmac_tutorial.py skrip.

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

Tambahkan header

Gunakan kode berikut untuk menambahkan header yang diperlukan.

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"

Menguji klien

Hubungi titik akhir dan periksa responsnya.

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

Membersihkan sumber daya

Untuk membersihkan dan menghapus langganan Communication Services, hapus sumber daya atau grup sumber daya. Menghapus grup sumber daya juga menghapus sumber daya apa pun yang terkait dengannya. Anda dapat mengetahui selengkapnya tentang cara membersihkan sumber daya Azure Communication Services dan membersihkan sumber daya Azure Functions.