C# 如何在.NET中使用Facebook签名的请求?
我正在使用Facebook作为我的web应用程序(ASP.NETMVC)的登录提供商 我的登录与另一个StackOverflow帖子类似。我也分享用户的担忧 我的登录流程如下: 1.用户按下登录按钮。 2.用户必须接受该应用程序。 3.javascript回调检索响应。 返回的对象:C# 如何在.NET中使用Facebook签名的请求?,c#,asp.net-mvc,facebook-javascript-sdk,asp.net-mvc-5,facebook-login,C#,Asp.net Mvc,Facebook Javascript Sdk,Asp.net Mvc 5,Facebook Login,我正在使用Facebook作为我的web应用程序(ASP.NETMVC)的登录提供商 我的登录与另一个StackOverflow帖子类似。我也分享用户的担忧 我的登录流程如下: 1.用户按下登录按钮。 2.用户必须接受该应用程序。 3.javascript回调检索响应。 返回的对象: { accessToken: "...", expiresIn: 1234, signedRequest: "...", userID:
{
accessToken: "...",
expiresIn: 1234,
signedRequest: "...",
userID: "123456789"
}
我听说我可以使用
signed_请求
来验证用户的请求,但是所有在线示例都是针对PHP的如何在.NET中执行此操作?是的,签名请求可用于验证传入的登录请求是否真实。如果您使用Javascript(例如,通过)登录用户,则可以使用已签名的_请求来确保数据不为假
根据,有3个主要步骤,不过我会更具体一点
- 字符串的第一部分(签名)是第二部分的散列
- 第二部分包含一些关于用户和请求的信息(用户ID、时间戳)
- 它们是,这意味着
和+
字符已替换为URL友好的/
和-
字符。用
替换+
字符,用-
替换/
字符 - 字符串可能没有完全填充Base64。Base64字符串应该可以被4整除;如有必要,用垫子把绳子垫起来
- 使用.NET类
areEqual
为true
,则您可以确保签名的请求有效且未被篡改(假设您的应用程序机密是安全的)
请记住对你的应用程序保密,否则恶意用户可能会做坏事。要将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("_", "/");
}
谢谢罗文 此代码有一个错误。它错误地计算了
expectedHash
,因此最终的areEqual
比较将失败。此行byte[]expectedHash=hmac.ComputeHash(Encoding.UTF8.GetBytes(dataRaw))
需要更改为byte[]expectedHash=hmac.ComputeHash(Encoding.UTF8.GetBytes(split[1])
@Rowan-我在“Facebook的工作场所”工作。在工作场所,我们也会有这个应用程序。卸载Workplace应用程序时,我能够获得已签名的\u请求。我可以使用您的方法解码有效负载以获取json对象,但我无法验证签名。
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);
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;
}
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);
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("_", "/");
}