【问题标题】:Get user profile information via ASP.NET Membership.OpenAuth通过 ASP.NET Membership.OpenAuth 获取用户配置文件信息
【发布时间】:2013-01-11 21:46:27
【问题描述】:

使用 Microsoft.AspNet.Membership.OpenAuth 我很快就能够通过各种外部提供商(facebook、twitter、google、microsoft)让应用程序登录用户。太好了。

我的问题是,我可以使用这个框架轻松获取用户的个人资料信息吗?如果服务有,我想获取他们的个人资料照片、电子邮件地址、出生日期等。

我知道 AuthenticationResult.ExtraData 中有一些额外的信息,但它不是标准的,也不包含我需要的内容。

我可以从这里做些什么来使用 Microsoft.AspNet.Membership.OpenAuth(或其他 .net lib)获取信息,或者我需要使用 ExtraData 中的访问令牌通过单独的手动访问不同的服务吗?服务 API?

谢谢

【问题讨论】:

  • +1 好问题,但我有预感,这主要取决于应用程序在每个提供程序上的设置方式。例如,如果您告诉 Facebook 您的应用程序应该请求访问联系人、图片、电子邮件等,那么当用户被重定向到 Facebook 的登录页面时,他应该明确授予您访问所有这些的权限。一旦您的网站被回调,您很可能可以访问所有这些信息......这只是我的猜测,我有兴趣看到一些答案。
  • 我认为您需要先向某些外部提供商注册您的网站,例如 Facebook,然后才能访问用户 Facebook 个人资料数据。
  • 您需要向大多数(如果不是全部)提供商注册,才能使用 OpenAuth 库登录。
  • 在 facebook 上,您需要在应用程序权限中专门询问电子邮件地址(在 developer.facebook.com 上)。今天早上再去看看,看看我要去哪里。

标签: c# asp.net oauth asp.net-membership membership-provider


【解决方案1】:

身份验证工作流程有两个主要问题需要克服。一个,正如 OP 正确指出的那样,涉及ExtraData 的内容,另一个涉及您需要向 Facebook 请求的权限。最后,我选择了DotNetOpenAuth 库而不是 Microsoft 库,但通过滚动我自己的类并在必要时借用部分框架,在某些地方扩展了它。

我做的第一件事是创建一个FacebookClient,它从DotNetOpenAuth 扩展了OAuth2Client,并允许我为scope 传递一个值,这超出了您可以从Facebook 请求数据的限制.我请求的权限是publish_stream, manage_pages, email, user_interests。它们只需附加到服务登录 URL 并传递给 Facebook。在我的OAuth2Client 实现中,有用的方法是GetUserData

    protected override IDictionary<string, string> GetUserData(string accessToken)
    {
        var token = accessToken.EscapeUriDataStringRfc3986();
        FacebookGraphData graphData;
        var request = WebRequest.Create(string.Format("https://graph.facebook.com/me?access_token={0}", token));
        using (var response = request.GetResponse())
        {
            using (var responseStream = response.GetResponseStream())
            {
                graphData = JsonHelper.Deserialize<FacebookGraphData>(responseStream);
            }
        }

        var userData = new Dictionary<string, string> {{"accessToken", accessToken}};
        userData.AddItemIfNotEmpty("id", graphData.Id);
        userData.AddItemIfNotEmpty("name", graphData.Name);
        userData.AddItemIfNotEmpty("email", graphData.Email);
        userData.AddItemIfNotEmpty("firstName", graphData.FirstName);
        userData.AddItemIfNotEmpty("lastName", graphData.LastName);
        userData.AddItemIfNotEmpty("link", graphData.Link == null ? null : graphData.Link.AbsoluteUri);
        userData.AddItemIfNotEmpty("username", graphData.Username);
        userData.AddItemIfNotEmpty("gender", graphData.Gender);
        userData.AddItemIfNotEmpty("locale", graphData.Locale);

        FacebookFriendData friendData;
        request = WebRequest.Create(string.Format("https://graph.facebook.com/me/friends?access_token={0}", token));
        using (var response = request.GetResponse())
        {
            using (var responseStream = response.GetResponseStream())
            {
                friendData = JsonHelper.Deserialize<FacebookFriendData>(responseStream);
            }
        }

        if (friendData.Friends != null)
        {
            userData.Add("connections", friendData.Friends.Count().ToString());
        }

        return userData;
    }

我基本上创建了一些数据类,当响应从 Facebook 返回时,这些数据类将被反序列化。我还可以从这里进行我需要的任何其他 Graph API 调用。序列化类如下所示:

[DataContract]
public class FacebookFriendData
{
    [DataMember(Name = "data")]
    public IEnumerable<Friend> Friends { get; set; }
}

[DataContract]
public class Friend
{
    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "name")]
    public string Name { get; set; }
}

[DataContract]
public class FacebookGraphData
{
    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "email")]
    public string Email { get; set; }

    [DataMember(Name = "first_name")]
    public string FirstName { get; set; }

    [DataMember(Name = "last_name")]
    public string LastName { get; set; }

    [DataMember(Name = "link")]
    public Uri Link { get; set; }

    [DataMember(Name = "username")]
    public string Username { get; set; }

    [DataMember(Name = "gender")]
    public string Gender { get; set; }

    [DataMember(Name = "locale")]
    public string Locale { get; set; }
}

根据@radm4,我仍然检查提供程序字符串以决定在某些地方调用哪些方法 - 仍在为该方法提供更优雅的解决方案...

【讨论】:

  • 感谢 levelnis,这基本上是我得出的结论,您的解决方案很好,因为它扩展了已有的内容,我想我也会尝试采用这种方式。跨度>
【解决方案2】:

环顾四周后,我找不到仅使用 Microsoft.AspNet.Membership.OpenAuth 的方法来做到这一点。

如果用户想使用 facebook,我的解决方案是跳过 .NET oauth 内容。在这种情况下,我使用 facebook C# SDK 进行身份验证,然后我可以访问电子邮件、生日、照片等。

if(provider != "facebook")
{
    //do normal oauth
}
else
{
                 FacebookClient client = new FacebookClient();

                var loginUrl = client.GetLoginUrl(new
                {
                    client_id = ConfigurationManager.AppSettings["facebookId"],
                    client_secret = ConfigurationManager.AppSettings["facebookClientSecret"],
                    redirect_uri = redirectUrl,
                    response_type = "code",
                    scope = "email,user_birthday"
                });

                Response.Redirect(loginUrl.AbsoluteUri);
}

当用户返回时,您可以使用 SDK 访问这些额外信息。

我也打算为 Google 添加这种类型的东西。如果用户想使用其他服务登录,他们可以,但我只会使用 asp.net oauth,在我有更多时间花在每个提供商上之前,他们不会获得像 facebook 或 google 那样的定制体验。

所以基本上答案是 ASP.net oauth 非常适合登录和非常基本的信息,但如果您需要更多信息,则需要为每个提供商扩展或绕过它。

【讨论】:

猜你喜欢
  • 2017-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-22
  • 2011-10-31
  • 1970-01-01
  • 2017-06-30
  • 2022-01-10
相关资源
最近更新 更多