【问题标题】:How do I use a Facebook signed_request in .NET?如何在 .NET 中使用 Facebook 签名请求?
【发布时间】:2014-03-02 00:15:43
【问题描述】:

我使用 Facebook 作为我的 Web 应用程序 (ASP.NET MVC) 的登录提供程序。

我的登录方式类似于另一个 StackOverflow 帖子 How to securely authorize a user via Facebook's Javascript SDK。我也分享用户的担忧。

我的登录流程如下:

1。用户按下登录按钮。

2。用户必须接受该应用。

3。 javascript 回调检索响应。

var authResponse = response.authResponse;

对象返回:

{
    accessToken: "...",
    expiresIn: 1234,
    signedRequest: "...",
    userID: "123456789"
}

我听说我可以使用signed_request 来验证用户的请求,但是所有在线示例都是针对 PHP 的如何在 .NET 中执行此操作?

【问题讨论】:

    标签: c# asp.net-mvc facebook-javascript-sdk asp.net-mvc-5 facebook-login


    【解决方案1】:

    将 Rowan 的答案编译成最终代码:

    public static string DecodeSignedRequest(string signed_request)
    {
        try
        {
            if (signed_request.Contains("."))
            {
                string[] split = signed_request.Split('.');
    
                string signatureRaw = FixBase64String(split[0]);
                string dataRaw = FixBase64String(split[1]);
    
                // the decoded signature
                byte[] signature = Convert.FromBase64String(signatureRaw);
    
                byte[] dataBuffer = Convert.FromBase64String(dataRaw);
    
                // JSON object
                string data = Encoding.UTF8.GetString(dataBuffer);
    
                byte[] appSecretBytes = Encoding.UTF8.GetBytes(app_secret);
                System.Security.Cryptography.HMAC hmac = new System.Security.Cryptography.HMACSHA256(appSecretBytes);
                byte[] expectedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(split[1]));
                if (expectedHash.SequenceEqual(signature))
                {
                    return data;
                }
            }
        }
        catch
        {
            // error
        }
        return "";
    }
    
    private static string FixBase64String(string str)
    {
        while (str.Length % 4 != 0)
        {
            str = str.PadRight(str.Length + 1, '=');
        }
        return str.Replace("-", "+").Replace("_", "/");
    }
    

    谢谢罗文!

    【讨论】:

      【解决方案2】:

      是的,signed_request 可用于验证传入的登录请求是否真实。如果您使用 Javascript 登录用户(例如通过 AJAX),您可以使用 signed_request 来确保数据不为假。

      根据Parsing the Signed Request,有3个主要步骤,但我会更具体一点。

      1. 获取 signed_request 字符串并将其拆分为两个字符串。有一个句点字符(句号)是delimiter
        • 字符串的第一部分(签名)是第二部分的哈希。
        • 第二部分包含有关用户和请求的一些信息(用户 ID、时间戳)。
      2. 字符串在Base64 中,但无法立即解码。
        • 它们是Base64-URL-encoded,这意味着+/ 字符已替换为URL 友好的-_ 字符。将- 字符替换为+,将_ 字符替换为/
        • 字符串可能未完全使用 Base64 填充。 Base64 字符串应该能被 4 整除;必要时垫出琴弦。
      3. 使用您的应用程序机密作为密钥,使用HMAC (SHA256) 对签名进行哈希处理,并将结果与​​提供的签名进行比较。

      1。拆分和解码

      代码

      string response = ""; // the signed_request
      
      string[] split = response.Split('.');
      
      string signatureRaw = FixBase64String(split[0]);
      string dataRaw = FixBase64String(split[1]);
      
      // the decoded signature
      byte[] signature = Convert.FromBase64String(signatureRaw);
      
      byte[] dataBuffer = Convert.FromBase64String(dataRaw);
      
      // JSON object
      string data = Encoding.UTF8.GetString(dataBuffer);
      

      FixBase64String()

      static string FixBase64String(string str)
      {
          string result = str;
      
          while (result.Length % 4 != 0)
          {
              result = result.PadRight(result.Length + 1, '=');
          }
      
          result = result.Replace("-", "+").Replace("_", "/");
      
          return result;
      }
      

      2。比较哈希

      byte[] appSecretBytes = Encoding.UTF8.GetBytes("my_app_secret_here");
      
      HMAC hmac = new HMACSHA256(appSecretBytes);
      
      byte[] expectedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(dataRaw));
      
      bool areEqual = expectedHash.SequenceEqual(signature);
      

      如果areEqualtrue,那么您可以确定签名请求是有效的并且没有被篡改(假设您的应用密码是安全的)。

      记得对你的应用保密,否则恶意用户可能会做坏事。

      【讨论】:

      • 这段代码有错误。它错误地计算了expectedHash,因此最终的areEqual 比较将失败。这行byte[] expectedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(dataRaw));需要改成byte[] expectedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(split[1]));
      • @Rowan - 我正在研究“Facebook 的工作场所”。在工作场所,我们也将拥有该应用程序。卸载 Workplace 应用程序后,我可以获取 signed_request。我可以使用您的方法解码有效负载以获取 json 对象,但我无法验证签名。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多