我一直在尝试让 Log Collector API 在 node.js Azure 函数中工作,但遇到 403/Forbidden 错误,这表明我没有正确形成授权标头。完整的代码在这里的 github 存储库中:
https://github.com/sportsmgmt-labs/Azure-Log-Analytics-Node-Function
数据收集器 API 文档在这里:
https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-data-collector-api
授权标头的格式应如下:
授权:SharedKey {WorkspaceID}:{Signature}
签名的编码/加密如下:
Base64(HMAC-SHA256(UTF8(StringToSign)))
这是我创建授权标头的代码:
var contentLength = Buffer.byteLength(req.body['log-entry'], 'utf8');
var authorization = 'POST\n' + contentLength + '\napplication/json\nx-ms-date:' + processingDate + '\n/api/logs';
// encode string using Base64(HMAC-SHA256(UTF8(StringToSign)))
authorization = crypto.createHmac('sha256', sharedKey).update(authorization.toString('utf8')).digest('base64');
authorization = 'Authorization: SharedKey ' + workspaceId + ':' + authorization;
服务器的响应是:
{"Error":"InvalidAuthorization","Message":"授权标头中指定了无效方案"}
有人可以帮我理解我做错了什么吗?谢谢!
编辑:这是执行此操作的 Python 代码:
def build_signature(customer_id, shared_key, date, content_length, method, content_type, resource):
x_headers = 'x-ms-date:' + date
string_to_hash = method + "\n" + str(content_length) + "\n" + content_type + "\n" + x_headers + "\n" + resource
bytes_to_hash = bytes(string_to_hash).encode('utf-8')
decoded_key = base64.b64decode(shared_key)
encoded_hash = base64.b64encode(hmac.new(decoded_key, bytes_to_hash, digestmod=hashlib.sha256).digest())
authorization = "SharedKey {}:{}".format(customer_id,encoded_hash)
return authorization
...和 C# 代码:
static void Main()
{
// Create a hash for the API signature
var datestring = DateTime.UtcNow.ToString("r");
string stringToHash = "POST\n" + json.Length + "\napplication/json\n" + "x-ms-date:" + datestring + "\n/api/logs";
string hashedString = BuildSignature(stringToHash, sharedKey);
string signature = "SharedKey " + customerId + ":" + hashedString;
PostData(signature, datestring, json);
}
// Build the API signature
public static string BuildSignature(string message, string secret)
{
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = Convert.FromBase64String(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hash = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hash);
}
}