简体   繁体   English

使用 C# 验证来自 Slack Events API 的请求

[英]Verify a request from Slack Events API with C#

This example in the Slack documentation uses a form-url-encoded body but the Slack Events Api sends json. Slack 文档中的此示例使用表单 url 编码的正文,但 Slack Events Api 发送 json。 I've attempted to implement the pseudo code in the example with the C# crypto namespace.我尝试使用 C# 加密命名空间实现示例中的伪代码。 Not able to get a matching signature.无法获得匹配的签名。

When I inspect the request body in C# it includes escaping for the quote (") characters which I'm pretty sure aren't in the request body when it's hashed on the Slack side. How can I know that my raw version of the request body matches what Slack used to create the hash? Is there something wrong with the way I'm using the HMACSHA256? Also looked at this but found nothing that I could extrapolate to C#.当我在 C# 中检查请求正文时,它包括对引号 (") 字符的转义,当它在 Slack 端散列时,我很确定它不在请求正文中。我怎么知道我的请求的原始版本body 匹配 Slack 用于创建哈希的内容?我使用 HMACSHA256 的方式有问题吗?也看过这个,但没有发现我可以推断到 C#。

{
...
    string signingKey = ConfigurationManager.AppSettings["Slack:SigningSecret"].ToString();            
    string timestamp = GetHeaderValue(actionContext, "X-Slack-Request-Timestamp");            
    string SlackSignature = GetHeaderValue(actionContext, "X-Slack-Signature");

    var app = HttpContext.Current;
    string requestBody = string.Empty;
    using (var stream = new MemoryStream())
    {
        app.Request.InputStream.Seek(0, SeekOrigin.Begin);
        app.Request.InputStream.CopyTo(stream);
        requestBody = Encoding.UTF8.GetString(stream.ToArray());                
        app.Request.InputStream.Seek(0, SeekOrigin.Begin);                
    }  

    string sig_basestring = "v0:" + timestamp + ":" + requestBody;
    var hmac256 = HMACSHA256.Create();
    hmac256.Key = Encoding.ASCII.GetBytes(signingKey);
    var sig_hash = 
    hmac256.ComputeHash(Encoding.ASCII.GetBytes(sig_basestring));

    var computedSignature = "v0=" + ToHex(sig_hash, false);
    bool isValidRequest = SlackSignature.Equals(computedSignature);

    if (!isValidRequest)
    {
        throw new HttpResponseException(HttpStatusCode.Forbidden);
    }
...
}

private string ToHex(byte[] bytes, bool upperCase) 
{
    var result = new StringBuilder(bytes.Length * 2)
    for (int i = 0; i < bytes.Length; i++)
            result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));
        return result.ToString();
    }

I came across SlackNet and found the solution that works:我遇到了SlackNet并找到了有效的解决方案:

var encoding = new UTF8Encoding();
using (var hmac = new HMACSHA256(encoding.GetBytes(signingSecret)))
{
    var hash = hmac.ComputeHash(encoding.GetBytes($"v0:{timestamp}:{requestBody}"));
    var hashString = $"v0={BitConverter.ToString(hash).Replace("-", "").ToLower(CultureInfo.InvariantCulture)}";
    if (hashString.Equals(SlackSignature)) return continuation();
}
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM