使用具有定义范围的 Facebook OAuth创建.NET ASP.NET MVC应用程序的最简单方法是什么?
我尝试了很多例子。OAuthWebSecurity.RegisterClient不支持添加更多 Facebook 范围。Facebook 应用程序模板创建一个画布,我需要非画布应用程序。FacebookScopedClient 未满,无法使用此修复程序。
你有什么建议?
我也开放 JavaScript/jQuery 解决方案。
使用具有定义范围的 Facebook OAuth创建.NET ASP.NET MVC应用程序的最简单方法是什么?
我尝试了很多例子。OAuthWebSecurity.RegisterClient不支持添加更多 Facebook 范围。Facebook 应用程序模板创建一个画布,我需要非画布应用程序。FacebookScopedClient 未满,无法使用此修复程序。
你有什么建议?
我也开放 JavaScript/jQuery 解决方案。
可能我来得太晚了,但是我几天前遇到了这个问题,我在网上发现只有几个糟糕的解决方案。所以我写了自己的解决方案,我现在只能发布它。
我利用了完成大部分工作的 DotNetOpenAuth.AspNet.Clients.OAuth2Client 类。我只是将其扩展到包括范围和额外的用户数据。
public class FacebookExtendedClient : DotNetOpenAuth.AspNet.Clients.OAuth2Client
{
protected FacebookClient facebookClient;
protected string fields;
protected string scope;
protected Func<string, object, string> fieldTransformer;
protected bool emailAsUsername;
protected IDictionary<string, string> userData;
private string[] splittedFields;
private string[] splittedScope;
protected const string serviceLoginBaseUrl = "https://www.facebook.com/dialog/oauth";
protected const string serviceMeBaseUrl = "https://graph.facebook.com/me";
protected const string serviceAccessTokenBaseUrl = "https://graph.facebook.com/oauth/access_token";
/// <summary>
/// Create an instrance of the class.
/// </summary>
/// <param name="appId">The App ID of the application used to connect to Facebook service.</param>
/// <param name="appSecret">The App Secret of the application used to connect to Facebook service.</param>
/// <param name="fields">
/// String containing comma separated fields to add to the request.
/// If empty the request will retrieve the default fields based of the specified scope.
/// </param>
/// <param name="fieldTransformer">
/// Function to be applied to the values retrived from facebook.
/// If null provided the method will try to cast values from object to string explicitly,
/// an InvalidCastException will be thrown if the cast will not be possible.
/// </param>
/// <param name="scope">
/// String containing comma separated permissions to add to the request.
/// If empty the request will have the basic scope.
/// </param>
/// <param name="emailAsUsername">Makes the email of the facebook user used as authentication username.</param>
public FacebookExtendedClient(string appId, string appSecret, string fields = "", Func<string, object, string> fieldTransformer = null, string scope = "", bool emailAsUsername = false)
: base("facebook")
{
if (string.IsNullOrEmpty(appId))
throw new ArgumentException("The appId argument can not be null or empty.", "appId");
if (string.IsNullOrEmpty(appSecret))
throw new ArgumentException("The appSecret argument can not be null or empty.", "appSecret");
fields = fields.Replace(" ", "");
scope = scope.Replace(" ", "");
this.splittedFields = fields.Split(',');
this.splittedScope = scope.Split(',');
if (emailAsUsername == true && !this.splittedFields.Contains("email") && !this.splittedScope.Contains("email"))
throw new ArgumentException("The scope argument must contain the 'email' permission and the 'email' field to allow emailAsUsername to true.", "scope");
this.facebookClient = new FacebookClient();
this.facebookClient.AppId = appId;
this.facebookClient.AppSecret = appSecret;
this.fields = fields;
this.fieldTransformer = fieldTransformer;
this.scope = scope;
this.emailAsUsername = emailAsUsername;
}
public FacebookClient FacebookClient
{
get
{
return this.facebookClient;
}
}
public IDictionary<string, string> UserData
{
get
{
return this.userData;
}
}
protected override Uri GetServiceLoginUrl(Uri returnUrl)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("redirect_uri", returnUrl.AbsoluteUri);
if (!string.IsNullOrEmpty(this.scope))
parameters.Add("scope", this.scope);
return this.facebookClient.GetLoginUrl(parameters);
}
protected override IDictionary<string, string> GetUserData(string accessToken)
{
// This method makes the AuthenticationResult's UserName property be the facebook username of the logged user,
// but if the facebook username is missing the facebook id will be used.
// If emailAsUsername is true then AuthenticationResult's UserName property is the email retrieved from facebook
// and the facebook username can be retrieved by the key "fb_username" in this.userData
FacebookClient facebookClient = new FacebookClient(accessToken);
var getResult = facebookClient.Get<IDictionary<string, object>>("me", new { fields = this.fields });
Dictionary<string, string> result = new Dictionary<string, string>();
if (this.fieldTransformer != null)
{
foreach (var pair in getResult)
result.Add(pair.Key, this.fieldTransformer(pair.Key, pair.Value));
}
else
{
foreach (var pair in getResult)
{
string value = pair.Value.ToString();
if (value == null)
throw new InvalidCastException("Cast not possible for the object associate to the key '" + pair.Key + "'.");
result.Add(pair.Key, value);
}
}
if (this.splittedFields.Contains("username"))
result["fb_username"] = result["username"];
if (this.emailAsUsername)
result["username"] = result["email"];
this.userData = result;
return result;
}
protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
{
UriBuilder builder = new UriBuilder(serviceAccessTokenBaseUrl);
builder.Query = string.Format("client_id={0}&client_secret={1}&redirect_uri={2}&code={3}",
this.facebookClient.AppId, this.facebookClient.AppSecret, HttpUtility.UrlEncode(Encoding.ASCII.GetBytes(returnUrl.AbsoluteUri)), authorizationCode);
using (WebClient client = new WebClient())
{
string str = client.DownloadString(builder.Uri);
if (string.IsNullOrEmpty(str))
return null;
return HttpUtility.ParseQueryString(str)["access_token"];
}
}
}
您也可以像这样在 OAuthWebSecurity 中注册它(将 RegisterAuth 方法放在 Application_Start 中,就像在 InternetApplication 模板中一样):
public static class AuthConfig
{
public static void RegisterAuth()
{
configuration.LoadFromAppSettings();
OAuthWebSecurity.RegisterClient(new FacebookExtendedClient(
"##YOUR_APP_ID##",
"##YOUR_APP_SECRET##",
"id,first_name,last_name,link,username,gender,email,age_range,picture.height(200)",
new Func<string, object, string>(fieldsTransformer),
"email"));
}
private static string fieldsTransformer(string key, object value)
{
switch (key)
{
case "picture":
var data = (value as IDictionary<string, object>)["data"] as IDictionary<string, object>;
return data["url"].ToString();
case "age_range":
var min = (value as IDictionary<string, object>)["min"];
return min.ToString();
default:
return value.ToString();
}
}
}
正如您在上面的示例中看到的,方法 fieldsTransformer 将获取所选字段的键和值,在这种情况下,它将 facebook 为图片检索的对象转换为图片的 url。这是一种方便的方法,如果为 Func 参数提供了 null,则将保存 values 对象的 JSON 表示。
稍后检索客户端信息,登录后,可以这样做:
[Authorize]
public class HomeController : Controller
{
public ActionResult Index()
{
IDictionary<string, string> userData = (OAuthWebSecurity.GetOAuthClientData("facebook").AuthenticationClient as FacebookExtendedClient).UserData;
string email = userData["email"];
// If leave null the fieldTransform of the client you can access to complex properties like this:
JObject picture = JObject.Parse(userData["picture"]);
string url = (picture["data"] as JObject)["url"].ToString();
ViewBag.Email = userData["email"];
ViewBag.PictureUrl = url;
return View();
}
}
希望你喜欢这段代码,即使有点晚了!:)
我正在 VS 2013 中使用 C# MVC 5 Web 应用程序编写我的第一个 Facebook 应用程序。
在 AppStart\StartupAuth.cs 文件中,我做了以下修改。
确保类中有以下 using 语句:
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Facebook;
using Owin;`
然后,在 ConfigureAuth 方法底部附近的 Facebook 身份验证部分:
FacebookAuthenticationOptions fbOptions = new FacebookAuthenticationOptions();
fbOptions.AppId="YOUR_APP_ID";
fbOptions.AppSecret="YOUR_APP_SECRET";
fbOptions.Scope.Add("user_about_me");
fbOptions.Scope.Add("user_actions.books");
fbOptions.Scope.Add("user_actions.music");
//...more at the bottom
fbOptions.Scope.Add("video_upload");
fbOptions.Scope.Add("xmpp_login");
app.UseFacebookAuthentication(fbOptions);
而已!以下是截至 2014 年 2 月 1 日的完整列表:
fbOptions.Scope.Add("user_about_me");
fbOptions.Scope.Add("user_actions.books");
fbOptions.Scope.Add("user_actions.music");
fbOptions.Scope.Add("user_actions.news");
fbOptions.Scope.Add("user_actions.video");
fbOptions.Scope.Add("user_activities");
fbOptions.Scope.Add("user_birthday");
fbOptions.Scope.Add("user_checkins");
fbOptions.Scope.Add("user_education_history");
fbOptions.Scope.Add("user_events");
fbOptions.Scope.Add("user_friends");
fbOptions.Scope.Add("user_games_activity");
fbOptions.Scope.Add("user_groups");
fbOptions.Scope.Add("user_hometown");
fbOptions.Scope.Add("user_interests");
fbOptions.Scope.Add("user_likes");
fbOptions.Scope.Add("user_location");
fbOptions.Scope.Add("user_notes");
fbOptions.Scope.Add("user_online_presence");
fbOptions.Scope.Add("user_photo_video_tags");
fbOptions.Scope.Add("user_photos");
fbOptions.Scope.Add("user_questions");
fbOptions.Scope.Add("user_relationship_details");
fbOptions.Scope.Add("user_relationships");
fbOptions.Scope.Add("user_religion_politics");
fbOptions.Scope.Add("user_status");
fbOptions.Scope.Add("user_subscriptions");
fbOptions.Scope.Add("user_videos");
fbOptions.Scope.Add("user_website");
fbOptions.Scope.Add("user_work_history");
fbOptions.Scope.Add("friends_about_me");
fbOptions.Scope.Add("friends_actions.books");
fbOptions.Scope.Add("friends_actions.music");
fbOptions.Scope.Add("friends_actions.news");
fbOptions.Scope.Add("friends_actions.video");
fbOptions.Scope.Add("friends_activities");
fbOptions.Scope.Add("friends_birthday");
fbOptions.Scope.Add("friends_checkins");
fbOptions.Scope.Add("friends_education_history");
fbOptions.Scope.Add("friends_events");
fbOptions.Scope.Add("friends_games_activity");
fbOptions.Scope.Add("friends_groups");
fbOptions.Scope.Add("friends_hometown");
fbOptions.Scope.Add("friends_interests");
fbOptions.Scope.Add("friends_likes");
fbOptions.Scope.Add("friends_location");
fbOptions.Scope.Add("friends_notes");
fbOptions.Scope.Add("friends_online_presence");
fbOptions.Scope.Add("friends_photo_video_tags");
fbOptions.Scope.Add("friends_photos");
fbOptions.Scope.Add("friends_questions");
fbOptions.Scope.Add("friends_relationship_details");
fbOptions.Scope.Add("friends_relationships");
fbOptions.Scope.Add("friends_religion_politics");
fbOptions.Scope.Add("friends_status");
fbOptions.Scope.Add("friends_subscriptions");
fbOptions.Scope.Add("friends_videos");
fbOptions.Scope.Add("friends_website");
fbOptions.Scope.Add("friends_work_history");
fbOptions.Scope.Add("ads_management");
fbOptions.Scope.Add("ads_read");
fbOptions.Scope.Add("create_event");
fbOptions.Scope.Add("create_note");
fbOptions.Scope.Add("email");
fbOptions.Scope.Add("export_stream");
fbOptions.Scope.Add("manage_friendlists");
fbOptions.Scope.Add("manage_notifications");
fbOptions.Scope.Add("manage_pages");
fbOptions.Scope.Add("photo_upload");
fbOptions.Scope.Add("publish_actions");
fbOptions.Scope.Add("publish_checkins");
fbOptions.Scope.Add("publish_stream");
fbOptions.Scope.Add("read_friendlists");
fbOptions.Scope.Add("read_insights");
fbOptions.Scope.Add("read_mailbox");
fbOptions.Scope.Add("read_page_mailboxes");
fbOptions.Scope.Add("read_requests");
fbOptions.Scope.Add("read_stream");
fbOptions.Scope.Add("rsvp_event");
fbOptions.Scope.Add("share_item");
fbOptions.Scope.Add("sms");
fbOptions.Scope.Add("status_update");
fbOptions.Scope.Add("video_upload");
fbOptions.Scope.Add("xmpp_login");