Как декодировать OAuth 2.0 для Canvas signed_request в С#?
Я могу успешно проверить подписанный запрос на приложение для холста Facebook, используя пример здесь, но я не могу декодировать полезную нагрузку. В документации на Facebook указано, что второй параметр в signed_request является объектом JSON с кодировкой base64url. В PHP полезная нагрузка декодируется с помощью json_decode:
$data = json_decode(base64_url_decode($payload), true);
Что такое эквивалент в С#?
Ответы
Ответ 1
Следующее должно помочь вам.
(Примечание: ссылка JObject - это JSON.NET, доступная через http://james.newtonking.com/projects/json-net.aspx и http://json.codeplex.com/)
Используемые пространства имен:
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json.Linq; // JSON.NET project
код:
public Dictionary<string,string> DecodePayload(string payload)
{
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var jObject = JObject.Parse(json);
var parameters = new Dictionary<string, string>();
parameters.Add("user_id", (string)jObject["user_id"] ?? "");
parameters.Add("oauth_token", (string)jObject["oauth_token"] ?? "");
var expires = ((long?) jObject["expires"] ?? 0);
parameters.Add("expires", expires > 0 ? expires.ToString() : "") ;
parameters.Add("profile_id", (string)jObject["profile_id"] ?? "");
return parameters;
}
Это то, что я использую в FaceSharp.. надеюсь, что это поможет
Ответ 2
Извините, бит StackOverflow noob, но для тех, кто пытается использовать метод JohnK для декодирования, он отлично работает, всего несколько советов по внедрению для таких, как я и другие, с проблемой кодирования base64....
Ссылка Json также доступна из nuGet
Install-Package Newtonsoft.Json
http://developers.facebook.com/docs/guides/canvas/#auth более подробно объясняет элемент [ "signed_request" ], но просто добавляет, когда Facebook отправляется назад (в моем случае после запрос регистрации пользователя), вы можете получить данные из сообщения, но строка находится в ДВЕ ЧАСТИХ, разделенных символом '.' - Таким образом, попытка декодирования [ "signed_request" ] завершится неудачей как "." не является базовым 64 char. Первая часть - это подпись, позволяющая подтвердить, что сообщение пришло из Facebook (только мы и они знаем, что сиг для декодирования), а вторая - полезная нагрузка.
Итак, я получил это для работы со следующим кодом (в контроллере MVC), источником является кнопка регистрации Facebook....
<fb:registration fields="name,email" redirect-uri="http://dev.devurlgoeshere.co.uk/Account/Register" width="530">
</fb:registration>
а затем код контроллера отвечает на запрос регистрации
[HttpPost]
public ActionResult Register(object postData )
{
string requestData = Request.Form["signed_request"];
string[] splitPayload = requestData.Split('.');
string sig = splitPayload[0];
string payload = splitPayload[1];
var decodedObj = DecodePayload(payload);
// get the items from the decodedObject
string userFacebookID = decodedObj["user_id"];
// now do what you want with their FacebookID
return View();
}
надеюсь, что это поможет кому-то, и извините, если это должно было быть редактирование/обратная связь или что-то еще...
Ответ 3
Тот же код, но без зависимости от Json.NET:
public IDictionary<string, object> DecodePayload(string payload)
{
string base64 = payload.PadRight(payload.Length + (4 - payload.Length % 4) % 4, '=')
.Replace('-', '+').Replace('_', '/');
string json = Encoding.UTF8.GetString(Convert.FromBase64String(base64));
return (IDictionary<string, object>)new JavaScriptSerializer().DeserializeObject(json);
}
Вы можете использовать его следующим образом:
public ActionResult Index()
{
var dict = DecodePayload(Request["signed_request"].Split('.')[1]);
return Content("Access Token: " + (string)dict["oauth_token"]);
}
Ответ 4
Посмотрите на .Net SDK на Codeplex http://facebooksdk.codeplex.com. Он будет обрабатывать всю "грязную работу" для вас. Например, я мог бы вызвать следующий код либо из действия контроллера, либо из Page_Load.
FacebookApp app = new FacebookApp();
string accessToken = app.Session.AccessToken;
long userId = app.UserId;
Вот оно. Вам не нужно беспокоиться о том, как facebook возвращает вам данные или расшифровывает их. SDK обрабатывает все, что для вас.
Ответ 5
Я меняю DecodePayload на это, и он отлично работает для меня:
public Dictionary<string, string> DecodePayload(string payload)
{
//Remove the bad part of signed_request
//Begin
string[] sB64String = payload.Split('.');
payload = payload.Replace((sB64String[0] + "."), string.Empty);
//End
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var jObject = JObject.Parse(json);
var parameters = new Dictionary<string, string>();
parameters.Add("user_id", (string)jObject["user_id"] ?? "");
parameters.Add("oauth_token", (string)jObject["oauth_token"] ?? "");
var expires = ((long?)jObject["expires"] ?? 0);
parameters.Add("expires", expires > 0 ? expires.ToString() : "");
parameters.Add("profile_id", (string)jObject["profile_id"] ?? "");
return parameters;
}
Ответ 6
Здесь, как это сделать, используя Facebook SDK
var parsedSignedRequest = FacebookSignedRequest.Parse(FacebookApplication.Current, signed_request);