如何使用ASP.NET MVC 5 OWIN得到Facebook的姓和名值?

问题描述 投票:20回答:8

我知道,“姓名”字段提供的,但我更愿意明确地访问姓和名。有人能帮助呢?我还在我的包裹周围ASP.Net MVC头部。

asp.net-mvc facebook asp.net-mvc-5 owin
8个回答
46
投票

在您的Startup.Auth.cs ConfigureAuth(IAppBuilder app)方法,设置为Facebook如下:

var x = new FacebookAuthenticationOptions();
        x.Scope.Add("email");
        x.AppId = "*";
        x.AppSecret = "**";
        x.Provider = new FacebookAuthenticationProvider()
        {
            OnAuthenticated = async context =>
                {
                    context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
                    foreach (var claim in context.User)
                    {
                        var claimType = string.Format("urn:facebook:{0}", claim.Key);
                        string claimValue = claim.Value.ToString();
                        if (!context.Identity.HasClaim(claimType, claimValue))
                            context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));

                    }

                }
        };

        x.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
        app.UseFacebookAuthentication(x);
        /*
        app.UseFacebookAuthentication(
           appId: "*",
           appSecret: "*");
         * */

然后用它来访问用户的登录信息:

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

然后将下面的拿到的第一个名字:

var firstNameClaim = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:first_name");

7
投票

Facebook的改变了它的权限的API。你可以在这里获得更多的信息:https://developers.facebook.com/docs/facebook-login/permissions

名称需要public_profile许可

var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
{
    AppId = "appId",
    AppSecret = "key"
};
facebookAuthenticationOptions.Scope.Add("email");
facebookAuthenticationOptions.Scope.Add("public_profile");
app.UseFacebookAuthentication(facebookAuthenticationOptions);

你可以用得到它:

var loginInfo = await authenticationManager.GetExternalLoginInfoAsync();
loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:name")

AuthenticationManager会是一个实例,你可以使用:

HttpContext.GetOwinContext().Authentication;

6
投票

不幸的是,因为Facebook的改变了他们的默认返回值与API更新2.4这个方法行不通了

它看起来像得到FIRST_NAME等的唯一方法是现在使用Facebook的图形API(like this posts suggests)。

我还发现this post的武士刀项目现场,解决这个问题,并已经提交pull请求,但尚未合并喷射。

希望这个保险柜别人的一点点时间;)


4
投票

2017年,这是为我工作(感谢David Poxon的码以上)的代码。请确保您已升级到Microsoft.Owin.Security.Facebook的3.1.0版本。

在Startup.Auth.cs(或Startup.cs在某些情况下),将以下代码:

app.UseFacebookAuthentication(new FacebookAuthenticationOptions()
{
    AppId = "***",
    AppSecret = "****",
    BackchannelHttpHandler = new HttpClientHandler(),
    UserInformationEndpoint = "https://graph.facebook.com/v2.8/me?fields=id,name,email,first_name,last_name",
    Scope = { "email" },
    Provider = new FacebookAuthenticationProvider()
    {
        OnAuthenticated = async context =>
        {
            context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
            foreach (var claim in context.User)
            {
                var claimType = string.Format("urn:facebook:{0}", claim.Key);
                string claimValue = claim.Value.ToString();
                if (!context.Identity.HasClaim(claimType, claimValue))
                    context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
            }
        }
    }
});

然后在您的控制器的外部登录回调方法,添加以下代码:

var firstName = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:first_name").Value;

同样,对于获得姓氏,用上面的线,代之以urn:facebook:first_nameurn:facebook:last_name


1
投票
 private Uri RedirectUri
        {
            get
            {
                var uriBuilder = new UriBuilder(Request.Url);
                uriBuilder.Query = null;
                uriBuilder.Fragment = null;
                uriBuilder.Path = Url.Action("FacebookCallback");
                return uriBuilder.Uri;
            }
    }

    [AllowAnonymous]
    public ActionResult Facebook()
    {
        var fb = new FacebookClient();
        var loginUrl = fb.GetLoginUrl(new
        {
            client_id = "296002327404***",
            client_secret = "4614cd636ed2029436f75c77961a8***",
            redirect_uri = RedirectUri.AbsoluteUri,
            response_type = "code",
            scope = "email" // Add other permissions as needed
        });

        return Redirect(loginUrl.AbsoluteUri);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        FormsAuthentication.SignOut();
        return View("Login");
    }
    public ActionResult FacebookCallback(string code)
    {
        var fb = new FacebookClient();
        dynamic result = fb.Post("oauth/access_token", new
        {
            client_id = "296002327404***",
            client_secret = "4614cd636ed2029436f75c77961a8***",
            redirect_uri = RedirectUri.AbsoluteUri,
            code = code
        });

        var accessToken = result.access_token;

        // Store the access token in the session for farther use
        Session["AccessToken"] = accessToken;

        // update the facebook client with the access token so 
        // we can make requests on behalf of the user
        fb.AccessToken = accessToken;

        // Get the user's information
        dynamic me = fb.Get("me?fields=first_name,middle_name,last_name,id,email");
        string email = me.email;
        string firstname = me.first_name;
        string middlename = me.middle_name;
        string lastname = me.last_name;

        db.Insert_customer(firstname,email,null,null,null,null,null,null,null,null,null,null,1,1,System.DateTime.Now,1,System.DateTime.Now);

        // Set the auth cookie
        FormsAuthentication.SetAuthCookie(email, false);
        return RedirectToAction("Index", "Home");
    }

}
}

1
投票

随着2019年1月,我想确认如何做到这一点,并提供一些额外的比特(有很多相互矛盾的信息在那里取决于答案写哪一年的!)。大卫和Waqas有最好的答案(IMO)。我使用MVC5,AspNetIdentity 2和3 IdentityServer。

首先,对于Facebook您的身份提供程序配置:

        app.UseFacebookAuthentication(new FacebookAuthenticationOptions
        {
            AuthenticationType = "facebook",
            Caption = "Login with Facebook",
            SignInAsAuthenticationType = signInAsType,

            AppId = ConfigurationManager.AppSettings["FacebookAppId"],
            AppSecret = ConfigurationManager.AppSettings["FacebookAppSecret"],

            Provider = new FacebookAuthenticationProvider()
            {
                OnAuthenticated = ctx =>
                {
                    foreach (var claim in ctx.User)
                    {
                        var claimType = $"urn:facebook:{claim.Key}";
                        var claimValue = claim.Value.ToString();
                        if (!ctx.Identity.HasClaim(claim.Key, claimValue))
                        {
                            ctx.Identity.AddClaim(new Claim(claim.Key, claimValue));
                        }
                    }
                    return Task.FromResult(0);
                }
            }
        });

不像一些其他的答案,这个结合了您在默认情况下会得到什么额外要求的领域,并采取urn:facebook:关要求的前面,所以它默认的要求命名方案相匹配。

你不需要添加任何附加ScopesFields(至少,不是姓和名)。 Microsoft.Owin.Security.Facebook的4.1版本已经这样做了你。该source code for the FacebookAuthenticationOptions is here。相关位:

    public FacebookAuthenticationOptions()
        : base(Constants.DefaultAuthenticationType)
    {
        Caption = Constants.DefaultAuthenticationType;
        CallbackPath = new PathString("/signin-facebook");
        AuthenticationMode = AuthenticationMode.Passive;
        Scope = new List<string>();
        BackchannelTimeout = TimeSpan.FromSeconds(60);
        SendAppSecretProof = true;
        _fields = new HashSet<string>();
        CookieManager = new CookieManager();

        AuthorizationEndpoint = Constants.AuthorizationEndpoint;
        TokenEndpoint = Constants.TokenEndpoint;
        UserInformationEndpoint = Constants.UserInformationEndpoint;

        Scope.Add("public_profile");
        Scope.Add("email");
        Fields.Add("name");
        Fields.Add("email");
        Fields.Add("first_name");
        Fields.Add("last_name");
    }

如果您正在使用IdentityServer 3(像我),那么你就需要抓住身份验证这些说法在您的自定义UserService像这样:

    public async override Task AuthenticateExternalAsync(ExternalAuthenticationContext ctx)
    {
        // first, lets see if we have enough data from this external provider
        // at a minimum, FirstName, LastName, and Email are required

        string email = null;
        string firstName = null;
        string lastName = null;

        var idp = ctx.ExternalIdentity.Provider;

        email = GetClaimValue(ctx, "email");

        if (idp == "google")
        {
            firstName = GetClaimValue(ctx, "given_name");
            lastName = GetClaimValue(ctx, "family_name");
        }
        else if (idp == "facebook")
        {
            firstName = GetClaimValue(ctx, "first_name");
            lastName = GetClaimValue(ctx, "last_name");
        }

        var missingClaims = "";
        if (email == null)
        {
            missingClaims = "email";
        }
        if (firstName == null)
        {
            if (missingClaims.Length > 0) { missingClaims += ", "; }
            missingClaims += "first name";
        }
        if (lastName == null)
        {
            if (missingClaims.Length > 0) { missingClaims += ", "; }
            missingClaims += "last name";
        }

        if (missingClaims.Length > 0)
        {
            var errorMessage = $"The external login provider didn't provide the minimum required user profile data.  Missing: {missingClaims}  " +
                "Verify that these fields are specified in your external login provider user profile and that you have allowed external apps (i.e. this one) access to them.  " +
                "Alternatively, you can try a different external login provider, or create a local acount right here.";
            ctx.AuthenticateResult = new AuthenticateResult(errorMessage);
            return;
        }

        var login = new Microsoft.AspNet.Identity.UserLoginInfo(ctx.ExternalIdentity.Provider, ctx.ExternalIdentity.ProviderId);
        var user = await _userManager.FindAsync(login);
        if (user == null)
        {
            // this user either does not exist or has not logged in with this identity provider
            // let's see if they already exist (by checking to see if there is a user account with this email address)

            user = await _userManager.FindByEmailAsync(email);
            if (user == null)
            {
                // there is no existing user with this email, therefore, a new user will be created
                user = new MotoTallyUser()
                {
                    Id = Guid.NewGuid(),
                    UserName = email,
                    Email = email,
                    EmailConfirmed = true,
                    FirstName = firstName,
                    LastName = lastName
                };
                await _userManager.CreateAsync(user);
                await _userManager.AddLoginAsync(user.Id, login);
            }
            else
            {
                // this user DOES exist (matched email provided by external login provider)
                // however, they have not logged in with this identity provider
                // therefore, update the user info with that reported by the external identity provider, and add the external login

                user.UserName = email;
                user.Email = email;
                user.EmailConfirmed = true;
                user.FirstName = firstName;
                user.LastName = lastName;
                await _userManager.UpdateAsync(user);
                await _userManager.AddLoginAsync(user.Id, login);
            }
        }
        else
        {
            // this user DOES exist (they already have an external login on record)
            // therefore, update the user info with that reported by the external identity provider (no need to add external login, its already there)

            user.UserName = email;
            user.Email = email;
            user.EmailConfirmed = true;
            user.FirstName = firstName;
            user.LastName = lastName;
            await _userManager.UpdateAsync(user);
        }

        ctx.AuthenticateResult = new AuthenticateResult(user.Id.ToString(), user.Email, null, ctx.ExternalIdentity.Provider);
        return;
    }

    private string GetClaimValue(ExternalAuthenticationContext ctx, string claimType)
    {
        if (ctx.ExternalIdentity.Claims.FirstOrDefault(x => x.Type == claimType) != null)
        {
            return ctx.ExternalIdentity.Claims.FirstOrDefault(x => x.Type == claimType).Value;
        }
        return null;
    }

希望这可以帮助别人!


0
投票

Facebook已经改变了他们的图形API返回值升级2.4。现在,你需要明确指定所有你想回去的字段。

查看从此注:facebook for developers Upgrade Info

在2.4版本的图形API的变化

在过去,从图形API调用的响应返回一组默认的字段。为了减少有效载荷的大小和改善延迟对移动网络,我们已经减少返回大多数图形API调用默认的字段数。在V2.4则需要声明列出响应字段您的来电。

为了从Facebook获取电子邮件,名字和姓氏:

首先,您需要安装Facebook SDK for .NET NuGet包

然后,在你startup.Auth.cs,改变Facebook的身份验证如下配置:

     app.UseFacebookAuthentication(new FacebookAuthenticationOptions
        {
            // put your AppId and AppSecret here. I am reading them from AppSettings 
            AppId = ConfigurationManager.AppSettings["FacebookAppId"],
            AppSecret = ConfigurationManager.AppSettings["FacebookAppSecret"],
            Scope = { "email" },
            Provider = new FacebookAuthenticationProvider
            {
                OnAuthenticated = context =>
                {
                    context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
                    return Task.FromResult(true);
                }
            }
        });

        // this is no longer needed
        //app.UseFacebookAuthentication(
        //   appId: ConfigurationManager.AppSettings["FacebookAppId"],
        //   appSecret: ConfigurationManager.AppSettings["FacebookAppSecret"]);

最后,在你的AccountController,添加以下代码ExternalLoginCallback方法:

if (string.Equals(loginInfo.Login.LoginProvider, "facebook", StringComparison.CurrentCultureIgnoreCase))
        {
            var identity = AuthenticationManager.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
            var access_token = identity.FindFirstValue("FacebookAccessToken");
            var fb = new FacebookClient(access_token);

            // you need to specify all the fields that you want to get back
            dynamic myInfo = fb.Get("/me?fields=email,first_name,last_name"); 
            string email = myInfo.email;
            string firstName = myInfo.first_name;
            string lastName = myInfo.last_name;
        }

facebook API Guid更多的参数,你可以回去了。


-3
投票

在Facebook的选择范围添加名字和姓氏

var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions()
            {
                AppId = "your app id",
                AppSecret = "your app secret",
            };

            facebookOptions.Scope.Add("email");
            facebookOptions.Scope.Add("first_name");
            facebookOptions.Scope.Add("last_name");
            return facebookOptions;
© www.soinside.com 2019 - 2024. All rights reserved.