通过ASP.NET Membership.OpenAuth获取用户配置文件信息

时间:2013-01-10 17:28:36

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

使用Microsoft.AspNet.Membership.OpenAuth我很快就能通过各种外部提供商(facebook,twitter,google,microsoft)获取应用程序。那很好。

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

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

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

由于

2 个答案:

答案 0 :(得分: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适合登录和非常基本的信息,但是如果你需要更多,你需要扩展或传递给每个提供商。

答案 1 :(得分:0)

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

我做的第一件事是创建一个FacebookClient,将OAuth2Client扩展为DotNetOpenAuth并允许我传递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,我仍然检查提供程序字符串以决定在某些地方调用哪些方法 - 仍在为这个方法提供更优雅的解决方案......