使用PowerShell验证MS Teams outgoing webhook的HMAC签名不匹配问题
Teams Outgoing Webhook HMAC签名验证错误原因及解决方案
错误原因
你之前的两种尝试都不符合微软的签名生成规则,问题出在:
- 对已解析的请求Body对象重新做JSON序列化:Teams生成签名时使用的是发送的原始JSON字符串,你自行用
ConvertTo-Json输出的字符串在键顺序、缩进、转义规则上和原始内容必然存在差异,会直接导致哈希结果不一致 - 仅提取
text字段计算:签名是针对完整的请求Body内容生成的,不是仅针对text字段 - 编码逻辑混乱:你先将序列化后的JSON转为UTF8字节,后续计算哈希时又用ASCII二次编码,编码不统一也会导致结果错误
正确签名计算规则
计算HMAC使用的消息是Teams发送的原始请求Body的完整UTF8编码字符串,未经过任何解析、修改、重新序列化。
正确验证代码
# Validate Message $enc = [System.Text.Encoding]::UTF8 # 核心:获取未经过解析修改的原始请求Body字符串,不要使用已经解析后的$Request.Body对象 $rawMessage = $Request.RawBody # 部分PowerShell Web框架可直接用$Request.InputStream读取原始内容转字符串 $messageBytes = $enc.GetBytes($rawMessage) $secret = '<Outgoing Webhook对应的安全令牌>' $hmacsha = New-Object System.Security.Cryptography.HMACSHA256 $hmacsha.Key = [Text.Encoding]::ASCII.GetBytes($secret) $computedHash = $hmacsha.ComputeHash($messageBytes) $computedSignature = [Convert]::ToBase64String($computedHash) $receivedSignature = ($Request.Headers.Authorization.Split(" "))[1] If ($computedSignature -eq $receivedSignature){ Write-Host "Authenticated" } else { Write-Host "Not authenticated" }
注意事项
- 读取原始Body时不要做任何字符修改,包括空格、换行、转义符的调整
- 消息体统一使用UTF8编码,密钥使用ASCII编码,不要混用编码规则
内容的提问来源于stack exchange,提问作者Daniel Fuhrer
相关产品推荐
相关产品推荐

