APIs que utilizam autenticação digest (AppKey e AppSecret) exigem que os clientes assinem cada requisição. Os SDKs do API Gateway realizam a assinatura automaticamente. Este tópico explica o processo de assinatura para implementações personalizadas de clientes.
Visão geral
O API Gateway gera e verifica assinaturas de requisição para:
Validar se as requisições contêm uma assinatura correta com base no AppKey autorizado.
Impedir a adulteração de requisições durante a transmissão.
Os provedores de API criam aplicativos na página Apps do console do API Gateway. Cada aplicativo possui um par de chaves de assinatura (AppKey e AppSecret). Após o provedor autorizar um aplicativo a chamar uma API, os chamadores usam o par de chaves para assinar as requisições. O aplicativo pode pertencer tanto ao provedor quanto ao chamador.
Quando um cliente chama uma API, ele assina a requisição com o par de chaves autorizado e adiciona o AppKey e a assinatura ao cabeçalho da requisição. O API Gateway lê o AppKey, recupera o AppSecret correspondente e recalcula a assinatura. Se a assinatura calculada coincidir com a assinatura do cliente, a requisição é encaminhada para o service de backend. Caso contrário, o API Gateway retorna um erro.
O API Gateway verifica assinaturas apenas para APIs com Security Authentication definido como Alibaba Cloud App.
Chamar APIs com SDKs
O API Gateway fornece SDKs com lógica de assinatura integrada e source code para Java, Android e Objective-C. Baixe-os no console do API Gateway:
Open API > SDKs
Call API > Authorized API SDK
Para mais informações, consulte Usar SDKs para chamar APIs.
Princípios da autenticação digest
3,1. Geração e verificação de assinatura
3,1,1. Pré-requisitos
O chamador da API obteve o par de chaves de assinatura para a API de destino.
APP Key
APP Secret
A Security Authentication da API de destino está definida como Alibaba Cloud App.
3,1,2. Geração de assinatura nos clientes
Para gerar uma assinatura:
Extraia os dados principais da requisição para obter uma string de assinatura.
Criptografe a string de assinatura com o AppSecret para produzir uma assinatura.
Adicione todos os cabeçalhos relacionados à assinatura à requisição HTTP.
3,1,3. Verificação de assinatura nos servidores
Para verificar uma assinatura de cliente:
Extraia os dados principais da requisição para construir uma string de assinatura.
Leia o AppKey da requisição e recupere o AppSecret correspondente.
Criptografe a string de assinatura com o AppSecret para produzir uma assinatura.
Compare a assinatura do lado do servidor com a assinatura do lado do cliente presente na requisição.
3,2. Geração e transferência de assinatura
3,2,1. Extração de uma string de assinatura
Extraia os dados principais da requisição HTTP e combine-os em uma string de assinatura no seguinte formato:
HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters
Esses campos são separados por \n. Se Headers estiver vazio, omita seu \n. Para outros campos vazios, mantenha o \n. A assinatura diferencia maiúsculas de minúsculas. Cada campo é extraído da seguinte forma:
HTTPMethod: o método HTTP usado para enviar a requisição (por exemplo, POST). Deve estar em maiúsculas.
Accept: o valor do cabeçalho Accept. Pode ser deixado vazio, mas recomendamos defini-lo explicitamente. Alguns clientes HTTP usam / como padrão, o que causa falha na verificação da assinatura.
-
Content-MD5: o valor do cabeçalho Content-MD5. Opcional.
Calculado apenas para requisições com corpo não-Form. Se o cliente omitir Content-MD5, o API Gateway ignora a validação.
Exemplo em Java para calcular Content-MD5:
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
Content-Type: o valor do cabeçalho Content-Type. Opcional.
Se ocorrer uma incompatibilidade de Content-Type (por exemplo, ao transferir arquivos por meio de um mini programa WeChat), adicione X-Ca-Signed-Content-Type:multipart/form-data como um cabeçalho personalizado. O API Gateway usa este cabeçalho para assinatura quando presente.
Date: o valor do cabeçalho Date. Opcional.
-
Headers: cabeçalhos personalizados a serem incluídos na assinatura. Regras de concatenação:
Ordene as chaves dos cabeçalhos alfabeticamente e concatene-as da seguinte forma:
HeaderKey1 + ":" + HeaderValue1 + "\n" + HeaderKey2 + ":" + HeaderValue2 + "\n" + ... HeaderKeyN + ":" + HeaderValueN + "\n"Se o valor de um cabeçalho estiver vazio, use HeaderKey + ":" + "\n" e mantenha a chave e os dois pontos (:).
Coloque as chaves de cabeçalho usadas para assinatura no cabeçalho X-Ca-Signature-Headers, separadas por vírgulas (,).
Os seguintes cabeçalhos não podem ser usados para cálculo de assinatura: X-Ca-Signature, X-Ca-Signature-Headers, Accept, Content-MD5, Content-Type e Date.
-
PathAndParameters: inclui todos os parâmetros Path, Query e Form.
Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueNOrdene as chaves dos parâmetros Query e Form alfabeticamente e concatene-as conforme mostrado acima.
Se os parâmetros Query e Form estiverem vazios, use apenas o Path sem anexar um ponto de interrogação (?).
Caso o valor de um parâmetro esteja vazio, use apenas a chave para a assinatura.
Para parâmetros de array com a mesma chave, mas valores diferentes, apenas o primeiro valor é usado na assinatura.
Exemplo de requisição HTTP:
POST /http2test/test?param1=test HTTP/1.1
host:api.aliyun.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
content-length:33
username=xiaoming&password=123456789
String de assinatura gerada para esta requisição:
POST
application/json; charset=utf-8
application/x-www-form-urlencoded; charset=utf-8
Wed, 09 May 2018 13:30:29 GMT+00:00
x-ca-key:203753385
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-signature-method:HmacSHA256
x-ca-timestamp:1525872629832
/http2test/test?param1=test&password=123456789&username=xiaoming
3,2,2. Cálculo da assinatura
Após combinar os dados principais em uma string de assinatura, criptografe e codifique-a para produzir a assinatura final. Algoritmos suportados:
HmacSHA256
HmacSHA1
Exemplos de criptografia, onde stringToSign é a string de assinatura e appSecret é o AppSecret:
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] appSecretBytes = appSecret.getBytes(Charset.forName("UTF-8"));
hmacSha256.init(new SecretKeySpec(appSecretBytes, 0, appSecretBytes.length, "HmacSHA256"));
byte[] md5Result = hmacSha256.doFinal(stringToSign.getBytes(Charset.forName("UTF-8")));
String signature = Base64.encodeBase64String(md5Result);
Mac hmacSha1 = Mac.getInstance("HmacSHA1");
byte[] appSecretBytes = appSecret.getBytes(Charset.forName("UTF-8"));
hmacSha1.init(new SecretKeySpec(appSecretBytes, 0, appSecretBytes.length, "HmacSHA1"));
byte[] md5Result = hmacSha1.doFinal(stringToSign.getBytes(Charset.forName("UTF-8")));
String signature = Base64.encodeBase64String(md5Result);
O StringToSign é decodificado como um array de bytes UTF-8, criptografado e então codificado em Base64 para produzir a assinatura final.
3,2,3. Transferência da assinatura
Inclua os seguintes cabeçalhos nas requisições enviadas ao API Gateway:
x-ca-key: o AppKey. Este parâmetro é obrigatório.
x-ca-signature-method: o método de assinatura. Este parâmetro é opcional. Valores válidos: HmacSHA256 e HmacSHA1. Valor padrão: HmacSHA256.
X-Ca-Signature-Headers: as chaves de todos os cabeçalhos de assinatura. Este parâmetro é opcional. Separe múltiplas chaves com vírgulas (,).
X-Ca-Signature: a assinatura. Este parâmetro é obrigatório.
Exemplo de requisição HTTP assinada:
POST /http2test/test?param1=test HTTP/1.1
host:api.aliyun.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-key:203753385
x-ca-signature-method:HmacSHA256
x-ca-signature-headers:x-ca-timestamp,x-ca-key,x-ca-nonce,x-ca-signature-method
x-ca-signature:xfX+bZxY2yl7EB/qdoDy9v/uscw3Nnj1pgoU+Bm6xdM=
content-length:33
username=xiaoming&password=123456789
3,3. Solução de problemas
Se a verificação da assinatura falhar, o API Gateway retorna o StringToSign do lado do servidor no cabeçalho de resposta X-Ca-Error-Message. Compare-o com o StringToSign do lado do cliente para identificar discrepâncias.
Se ambas as strings coincidirem, verifique o AppSecret usado para a assinatura.
Os cabeçalhos HTTP não suportam quebras de linha. As quebras de linha no StringToSign são substituídas por sinais de cerquilha (#).
errorMessage: Invalid Signature, Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`
Exemplo de string de assinatura do lado do servidor:
GET
application/json
application/json
X-Ca-Key:200000
X-Ca-Timestamp:1589458000000
/app/v1/config/keys?keys=TEST