如何在Azure API Management策略中生成HMAC SHA256的Hex Digest
Slack API签名验证(Azure APIM)修正方案
问题根源
你当前得到的Hex Digest长度不符合Slack要求(标准SHA256签名应为64位小写十六进制字符串),核心原因包括:
- 未严格遵循Slack的签名拼接规则,遗漏了强制要求的
v0:前缀 - 哈希结果的十六进制转换方式错误,未确保每个字节对应两位字符
- 字符串转字节数组时未使用UTF8编码,与Slack的签名计算逻辑不匹配
关键修正步骤
构建合规的签名基字符串
必须按照Slack要求的格式拼接:v0:{timestamp}:{request_body},其中:v0是固定版本前缀,不可省略timestamp取请求头X-Slack-Request-Timestamp的原始值request_body为未修改的原始请求体内容
正确计算HMAC SHA256哈希
使用Slack提供的Signing Secret作为密钥,以UTF8编码将基字符串转为字节数组,计算哈希后将每个字节转为两位小写十六进制字符,确保最终结果为64位长度。准确对比签名
从请求头X-Slack-Signature中提取v0=之后的部分,再与计算出的签名做等值对比。
修正后的Azure APIM策略代码
<set-variable name="slackSigningSecret" value="{{slack-signing-secret}}" /> <set-variable name="timestamp" value="@context.Request.Headers.GetValueOrDefault('X-Slack-Request-Timestamp', '')" /> <set-variable name="requestBody" value="@context.Request.Body.As<string>(preserveContent: true)" /> <!-- 构建Slack要求的签名基字符串 --> <set-variable name="signatureBaseString" value="@($"v0:{(string)context.Variables["timestamp"]}:{(string)context.Variables["requestBody"]}")" /> <!-- 计算HMAC SHA256并转为64位小写十六进制字符串 --> <set-variable name="computedSignature" value="@(System.Security.Cryptography.HMACSHA256.HashData( System.Text.Encoding.UTF8.GetBytes((string)context.Variables["slackSigningSecret"]), System.Text.Encoding.UTF8.GetBytes((string)context.Variables["signatureBaseString"]) ).Select(b => b.ToString("x2")).Aggregate((a, b) => a + b))" /> <!-- 提取Slack发送的签名内容 --> <set-variable name="slackSignature" value="@(context.Request.Headers.GetValueOrDefault('X-Slack-Signature', '').Split('=').LastOrDefault())" /> <!-- 签名验证逻辑 --> <choose> <when condition="@((string)context.Variables["computedSignature"] != (string)context.Variables["slackSignature"])"> <return-response> <set-status code="403" reason="Invalid Slack Signature" /> </return-response> </when> </choose>
验证要点
- 确认
slack-signing-secret是Slack控制台提供的正确密钥 - 确保请求体未被APIM修改,通过
preserveContent: true保留原始内容 - 检查时间戳与Slack请求头的一致性,避免时间差超过5分钟导致验证失败
内容的提问来源于stack exchange,提问作者JackMorrison
相关产品推荐
相关产品推荐

