【问题标题】:How to get Facebook first and last name values using ASP.NET MVC 5 and OWIN?如何使用 ASP.NET MVC 5 和 OWIN 获取 Facebook 名字和姓氏值?
【发布时间】:2014-01-22 14:46:37
【问题描述】:

我知道提供了“姓名”字段,但我更愿意明确访问名字和姓氏。有人可以帮忙吗?我还在纠结 ASP.Net MVC。

【问题讨论】:

    标签: asp.net-mvc facebook asp.net-mvc-5 owin


    【解决方案1】:

    在您的 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");
    

    【讨论】:

    • 为我工作 - 然后仍然需要将价值从提供者中提取出来,我目前正在做的事情就像 public string FirstName { get { return chainValue( "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", // Google "urn:facebook:first_name" // Facebook ); } }
    【解决方案2】:

    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;
    

    【讨论】:

    • 嗨,loginInfo 来自哪里?我们应该把这行代码放在哪里?
    • 嗨,我编辑了答案,如果仍然缺少任何内容,请告诉我。保重!
    • 这对我有用;我可以得到名字+姓氏。但电子邮件始终是null。另外,您知道分别获取名字和姓氏的方法吗?
    • 对我来说,姓名、名字和姓氏是null
    【解决方案3】:

    不幸的是,由于 Facebook 使用 API 更新 2.4 更改了其默认返回值,此方法不再有效

    现在获取 first_name 等的唯一方法似乎是使用 Facebook Graph API (like this posts suggests)。

    我还在 Katana 项目网站上找到了解决此问题的 this post,并且已经提交了拉取请求,但尚未合并 jet。

    希望这可以为某人节省一点时间;)

    【讨论】:

      【解决方案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_name替换为urn:facebook:last_name

      【讨论】:

        【解决方案5】:
         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");
            }
        
        }
        }
        

        【讨论】:

          【解决方案6】:

          截至 2019 年 1 月,我想确认如何执行此操作并提供一些额外的信息(有很多相互矛盾的信息,具体取决于答案的编写年份!)。 David 和 Waqas 有最好的答案 (IMO)。我正在使用 MVC5、AspNetIdentity 2 和 IdentityServer 3。

          首先,您的 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;
              }
          

          希望这对某人有所帮助!

          【讨论】:

            【解决方案7】:

            对于 VB.NET 开发人员,这是 Startup.Auth.vb 中的代码

            Dim fb = New FacebookAuthenticationOptions()
                    fb.Scope.Add("email")
                    fb.AppId = "*"
                    fb.AppSecret = "*"
                    fb.Provider = New FacebookAuthenticationProvider() With
                    {
                        .OnAuthenticated = Async Function(context)
                                               context.Identity.AddClaim(New System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken))
            
                                               For Each claim In context.User
                                                   Dim claimType = String.Format("urn:facebook:{0}", claim.Key)
                                                   Dim claimValue As String = claim.Value.ToString()
                                                   If Not context.Identity.HasClaim(claimType, claimValue) Then context.Identity.AddClaim(New System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"))
                                               Next
                                           End Function
                    }
            
                    fb.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie
                    app.UseFacebookAuthentication(fb)
            

            【讨论】:

              【解决方案8】:

              Facebook 在升级 2.4 中改变了他们的 Graph API 返回值的方式。现在您需要明确指定您想要返回的所有字段。

              请参阅此说明:facebook for developers Upgrade Info:

              2.4 版中的图形 API 更改

              过去,来自 Graph API 调用的响应会返回一组默认字段。为了减少有效载荷大小并改善移动设备的延迟 我们减少了返回的默认字段数量的网络 大多数 Graph API 调用。在 v2.4 中,您需要以声明方式列出 您的呼叫的响应字段。

              从 facebook 获取电子邮件、名字和姓氏:

              首先需要安装Facebook SDK for .NETnuget包

              然后,在您的 startup.Auth.cs 中,将 Facebook Authentication 的配置更改如下:

                   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 了解更多您可以取回的参数。

              【讨论】:

                【解决方案9】:

                在 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;
                

                【讨论】:

                • first_name 和 last_name 不是有效范围。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-01-27
                • 1970-01-01
                • 2022-08-04
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多