Assinar uma solicitação HTTP
Neste tutorial, você aprenderá como assinar uma solicitação HTTP com uma assinatura HMAC.
Nota
Recomendamos vivamente a utilização dos SDKs do Azure. A abordagem descrita aqui é uma opção de fallback para casos em que os SDKs do Azure não podem ser usados por qualquer motivo.
Pré-requisitos
Antes de começar, certifique-se de:
- Crie uma conta do Azure com uma assinatura ativa. Para obter detalhes, consulte Criar uma conta gratuitamente.
- Instalar o Visual Studio.
- Criar um recurso do Azure Communication Services. Para obter detalhes, consulte Criar um recurso dos Serviços de Comunicação do Azure. Você precisará registrar seu resourceEndpoint e resourceAccessKey para este tutorial.
Assinar uma solicitação HTTP com C#
A autenticação de chave de acesso usa uma chave de segredo compartilhado para gerar uma assinatura HMAC para cada solicitação HTTP. Essa assinatura é gerada com o algoritmo SHA256 e é enviada no Authorization
cabeçalho usando o HMAC-SHA256
esquema. Por exemplo:
Authorization: "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=<hmac-sha256-signature>"
Os hmac-sha256-signature
são constituídos por:
- Verbo HTTP (por exemplo,
GET
ouPUT
) - Caminho de solicitação HTTP
- data-ms x
- Host
- x-ms-content-sha256
Configurar
As etapas a seguir descrevem como construir o cabeçalho de autorização.
Criar um novo aplicativo C#
Em uma janela de console, como cmd, PowerShell ou Bash, use o dotnet new
comando para criar um novo aplicativo de console com o nome SignHmacTutorial
. Este comando cria um projeto C# "Hello World" simples com um único arquivo de origem: Program.cs.
dotnet new console -o SignHmacTutorial
Altere seu diretório para a pasta do aplicativo recém-criada. Use o dotnet build
comando para compilar seu aplicativo.
cd SignHmacTutorial
dotnet build
Instalar o pacote
Instale o pacote Newtonsoft.Json
usado para a serialização do corpo.
dotnet add package Newtonsoft.Json
Atualize a declaração de método para oferecer suporte a código assíncrono Main
. Use o código a seguir para começar.
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.
}
}
}
Criar uma mensagem de solicitação
Neste exemplo, assinaremos uma solicitação para criar uma nova identidade usando a API de Autenticação dos Serviços de Comunicação (versão 2021-03-07
).
Adicione o seguinte código ao método 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")
};
Substitua resourceEndpoint
pelo valor real do ponto final do recurso.
Criar um hash de conteúdo
O hash de conteúdo faz parte da assinatura HMAC. Utilize o código seguinte para calcular o hash de conteúdo. Você pode adicionar esse método a Program.cs
sob o Main
método.
static string ComputeContentHash(string content)
{
using var sha256 = SHA256.Create();
byte[] hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(content));
return Convert.ToBase64String(hashedBytes);
}
Calcular uma assinatura
Use o código a seguir para criar um método para calcular sua assinatura 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);
}
Substitua resourceAccessKey
por uma chave de acesso do seu recurso real de Serviços de Comunicação.
Criar uma cadeia de caracteres de cabeçalho de autorização
Agora vamos construir a cadeia de caracteres que adicionaremos ao nosso cabeçalho de autorização.
- Prepare valores para os cabeçalhos a serem assinados.
- Especifique o carimbo de data/hora atual usando o fuso horário UTC (Tempo Universal Coordenado).
- Obtenha a autoridade de solicitação (nome de host DNS ou endereço IP e o número da porta).
- Calcule um hash de conteúdo.
- Prepare uma cadeia de caracteres para assinar.
- Calcule a assinatura.
- Concatene a cadeia de caracteres, que será usada no cabeçalho de autorização.
Adicione o seguinte código ao método 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}";
Adicionar cabeçalhos a requestMessage
Use o código a seguir para adicionar os cabeçalhos necessários ao seu 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);
Testar o cliente
Chame o ponto de extremidade usando HttpClient
e verifique a resposta.
HttpClient httpClient = new HttpClient
{
BaseAddress = requestUri
};
var response = await httpClient.SendAsync(requestMessage);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
Pré-requisitos
Antes de começar, certifique-se de:
- Crie uma conta do Azure com uma assinatura ativa. Para obter detalhes, consulte Criar uma conta gratuitamente.
- Baixe e instale o Python.
- Baixe e instale o Visual Studio Code ou outro IDE que ofereça suporte a Python.
- Criar um recurso do Azure Communication Services. Para obter detalhes, consulte Criar um recurso dos Serviços de Comunicação do Azure. Você precisará de seus resource_endpoint_name e resource_endpoint_secret para este tutorial.
Assinar uma solicitação HTTP com Python
A autenticação de chave de acesso usa uma chave de segredo compartilhado para gerar uma assinatura HMAC para cada solicitação HTTP. Essa assinatura é gerada com o algoritmo SHA256 e é enviada no Authorization
cabeçalho usando o HMAC-SHA256
esquema. Por exemplo:
Authorization: "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=<hmac-sha256-signature>"
Os hmac-sha256-signature
são constituídos por:
- Verbo HTTP (por exemplo,
GET
ouPUT
) - Caminho de solicitação HTTP
- data-ms x
- Host
- x-ms-content-sha256
Configurar
As etapas a seguir descrevem como construir o cabeçalho de autorização.
Criar um novo script Python
Abra o Visual Studio Code ou outro IDE ou editor de sua escolha e crie um novo arquivo chamado sign_hmac_tutorial.py
. Salve este arquivo em uma pasta conhecida.
Adicionar importações necessárias
Atualize o sign_hmac_tutorial.py
script com o seguinte código para começar.
import base64
import hashlib
import hmac
import json
from datetime import datetime, timezone
from urllib import request
Preparar dados para o pedido
Neste exemplo, assinaremos uma solicitação para criar uma nova identidade usando a API de Autenticação dos Serviços de Comunicação (versão2021-03-07
).
Adicione o seguinte código ao sign_hmac_tutorial.py
script.
- Substitua
resource_endpoint_name
pelo valor real do nome do ponto de extremidade do recurso. Esse valor pode ser encontrado na seção Visão geral do seu recurso dos Serviços de Comunicação do Azure. É o valor de "Endpoint" após "https://". - Substitua
resource_endpoint_secret
pelo valor secreto do ponto de extremidade do recurso real. Esse valor pode ser encontrado na seção Chaves do seu recurso dos Serviços de Comunicação do Azure. É o valor de "Key" - primário ou secundário.
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")
Criar um hash de conteúdo
O hash de conteúdo faz parte da assinatura HMAC. Utilize o código seguinte para calcular o hash de conteúdo. Você pode adicionar esse método ao sign_hmac_tutorial.py
script.
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
Calcular uma assinatura
Use o código a seguir para criar um método para calcular sua assinatura 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
Obter o carimbo de data/hora UTC atual de acordo com o padrão RFC1123
Use o código a seguir para obter o formato de data desejado independentemente das configurações de localidade.
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)
Criar uma cadeia de caracteres de cabeçalho de autorização
Agora vamos construir a cadeia de caracteres que adicionaremos ao nosso cabeçalho de autorização.
- Prepare valores para os cabeçalhos a serem assinados.
- Especifique o carimbo de data/hora atual usando o fuso horário UTC (Tempo Universal Coordenado).
- Obtenha a autoridade de solicitação (nome de host DNS ou endereço IP e o número da porta).
- Calcule um hash de conteúdo.
- Prepare uma cadeia de caracteres para assinar.
- Calcule a assinatura.
- Concatene a cadeia de caracteres, que será usada no cabeçalho de autorização.
Adicione o seguinte código ao sign_hmac_tutorial.py
script.
# 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}"
Adicionar cabeçalhos
Use o código a seguir para adicionar os cabeçalhos necessários.
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"
Testar o cliente
Ligue para o ponto de extremidade e verifique a resposta.
req = request.Request(request_uri, content, request_headers, method='POST')
with request.urlopen(req) as response:
response_string = json.load(response)
print(response_string)
Clean up resources (Limpar recursos)
Para limpar e remover uma assinatura dos Serviços de Comunicação, exclua o recurso ou grupo de recursos. A exclusão do grupo de recursos também exclui quaisquer outros recursos associados a ele. Você pode saber mais sobre como limpar os recursos dos Serviços de Comunicação do Azure e limpar os recursos do Azure Functions.
Próximos passos
Você também pode querer: