2

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

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

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

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

谢谢

4

2 回答 2

0

环顾四周后,我看不到仅使用 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 访问这些额外信息。

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

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

于 2013-01-11T12:36:46.413 回答
0

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

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

    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,我仍然检查提供程序字符串以决定在某些地方调用哪些方法 - 仍在为该方法开发更优雅的解决方案......

于 2013-01-11T13:46:27.727 回答