asp.net Google身份验证获取用户个人资料图片

dgenwo3n  于 2022-12-01  发布在  .NET
关注(0)|答案(3)|浏览(163)

如果用户是通过谷歌认证,我需要得到他的个人资料图片。
如果用户是通过Facebook验证我得到他的个人资料图片与此代码:

var info = await _signInManager.GetExternalLoginInfoAsync();
var identifier = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier); 
var picture = $"https://graph.facebook.com/{identifier}/picture"; // 3

那么,我需要使用哪段代码在3行中获取用户的个人资料图片,以防用户通过谷歌认证?

pxy2qtax

pxy2qtax1#

访问用户配置文件图片,完整解决方案。
堆栈:
ASP网络身份4 v4 + ASP网络身份+ Google People Api

步骤

1.准备

1.1我使用默认的HttpClient生成对Google API的HTTP请求
1.2安装NUGET System.Net.Http.Json以简化序列化。1.3使用[json to c#]工具,创建如下所示的DTO:

/// <summary>
    /// 🟡 official docs.
    /// https://developers.google.com/people/api/rest/v1/people#Person.Photo
    /// </summary>
    public class PeopleApiPhotos    {
        
        public string resourceName { get; set; } 
        public string etag { get; set; } 
        public List<Photo> photos { get; set; }
        
        public class Source    {
            public string type { get; set; } 
            public string id { get; set; } 
        }

        public class Metadata    {
            public bool primary { get; set; } 
            public Source source { get; set; } 
        }

        public class Photo    {
            public Metadata metadata { get; set; } 
            public string url { get; set; } 
        }
    }

2.身份服务器:当用户确认外部信息数据后,发送http get请求,检索头像图片url:

  • 具有Asp Net身份的身份服务器〉登录〉OnPostConfirmationAsync:完整方法 *
public async Task < IActionResult > OnPostConfirmationAsync(string returnUrl = null) {
  returnUrl = returnUrl ? ?Url.Content("~/");
  // Get the information about the user from the external login provider
  var info = await _signInManager.GetExternalLoginInfoAsync();
  if (info == null) {
    ErrorMessage = "Error loading external login information during confirmation.";
    return RedirectToPage("./Login", new {
      ReturnUrl = returnUrl
    });
  }

  // try to get profile picture
  string pictureUri = string.Empty;

  if (info.LoginProvider.ToLower() == "google") {
    var httpClient = _httpClientFactory.CreateClient();
    string peopleApiKey = _configuration["GoogleApiKey:PeopleApiKey"];;
    var googleAccountId = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
    var photosResponse = await httpClient.GetFromJsonAsync < PeopleApiPhotos > (
    $ "https://people.googleapis.com/v1/people/{googleAccountId}?personFields=photos&key={peopleApiKey}");
    pictureUri = photosResponse ? .photos.FirstOrDefault() ? .url;
  }

  if (ModelState.IsValid) {
    // Cria usuário
    var user = new AppUser {
      UserName = Input.Email,
      Email = Input.Email,
      FirstName = Input.FirstName,
      LastName = Input.LastName,
      ProfilePictureUrl = pictureUri
    };

    var result = await _userManager.CreateAsync(user);
    if (result.Succeeded) {
      result = await _userManager.AddLoginAsync(user, info);
      if (result.Succeeded) {
        _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);

        var userId = await _userManager.GetUserIdAsync(user);
        var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
        code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
        var callbackUrl = Url.Page("/Account/ConfirmEmail", pageHandler: null, values: new {
          area = "Identity",
          userId = userId,
          code = code
        },
        protocol: Request.Scheme);

        await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $ "Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

        // If account confirmation is required, we need to show the link if we don't have a real email sender
        if (_userManager.Options.SignIn.RequireConfirmedAccount) {
          return RedirectToPage("./RegisterConfirmation", new {
            Email = Input.Email
          });
        }

        await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider);

        return LocalRedirect(returnUrl);
      }
    }
    foreach(var error in result.Errors) {
      ModelState.AddModelError(string.Empty, error.Description);
    }
  }

  ProviderDisplayName = info.ProviderDisplayName;
  ReturnUrl = returnUrl;
  return Page();
}

2.1具有Asp Net身份的身份服务器〉登录〉在后确认异步时:亮点:

这️只是上面完整方法的一小部分。

  • 检查外部提供商是否为Google,并使用[名称标识符]和[Google Api密钥]访问 People Endpoint。*
// try to get profile picture
string pictureUri = string.Empty;

if (info.LoginProvider.ToLower() == "google") {
  var httpClient = _httpClientFactory.CreateClient();
// ApiKey can get generated in [Google Developers Console](https://console.developers.google.com/apis/credentials).
  string peopleApiKey = _configuration["GoogleApiKey:PeopleApiKey"];;
  var googleAccountId = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
  var photosResponse = await httpClient.GetFromJsonAsync < PeopleApiPhotos > (
  $ "https://people.googleapis.com/v1/people/{googleAccountId}?personFields=photos&key={peopleApiKey}");
  pictureUri = photosResponse ? .photos.FirstOrDefault() ? .url;
}

3. Identity Server〉配置文件服务实施:

public async Task GetProfileDataAsync(ProfileDataRequestContext context) {
  var sub = context.Subject.GetSubjectId();
  var user = await _userManager.FindByIdAsync(sub);
  var principal = await _claimsFactory.CreateAsync(user);

  var claims = principal.Claims.ToList();

  claims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName));
  claims.Add(new Claim(JwtClaimTypes.FamilyName, user.LastName));

  // Insert a new claim, that gets ProfilePictureUrl persisted in my app user in database.
  claims.Add(new Claim(JwtClaimTypes.Picture, user.ProfilePictureUrl));

  context.IssuedClaims = claims;
}

4.在ReactJS前端访问配置文件用户:

为了在前端获得用户配置文件数据,我使用OidcClient-js

// here i'm using oidc-client.js
// user object is loaded with user full data.
let profilePictureUrl = user.profile.picture;

感谢@DaImTo的回复。

mnowg1ta

mnowg1ta2#

People.get方法会传回包含
您的用户需要使用配置文件范围进行身份验证。

原始http请求

GET https://people.googleapis.com/v1/people/me?personFields=photos HTTP/1.1

Authorization: Bearer [YOUR_ACCESS_TOKEN]
Accept: application/json

响应

{
  "resourceName": "people/117200475532672775346",
  "etag": "%EgQBAzcuGgQBAgUHIgxHcHNCRHZycjVkZz0=",
  "photos": [
    {
      "metadata": {
        "primary": true,
        "source": {
          "type": "PROFILE",
          "id": "1172004755672775346"
        }
      },
      "url": "https://lh3.googleusercontent.com/a-/AOh14GhroCYJp2P9xeYeYk1npchBPK-zbtTxzNQo0WAHI20=s100"
    },
    {
      "metadata": {
        "source": {
          "type": "CONTACT",
          "id": "3faa96eb0baa4be"
        }
      },
      "url": "https://lh6.googleusercontent.com/-vuhaM1mUvwE/VFOBzFDW-TI/AAAAAAAAAAA/izR9rgfDIyoVoHd7Mq_OJmdbwjhEnfhEQCOQCEAE/s100/photo.jpg"
    }
  ]
}

注:您也可以从用户信息端点获得此信息,但谷歌不保证他们会发送索赔每次您提出的要求,所以IMO的最好去通过人民API。

ql3eal8s

ql3eal8s3#

我尝试了你显示的模式来获得个人资料图片,所以我可以接收人名,但它不能绑定..我指的是@gabrielbarceloscn的答案..

public class PeopleApiNames
    {
        public string resourceName { get; set; }

        public string etag { get; set; }

        public List<Name> names { get; set; }

        public class Source
        {
            public string type { get; set; }

            public string id { get; set; }
        }

        public class Metadata
        {
            public bool primary { get; set; }

            public Source source { get; set; }
        }

        public class Name
        {
            public Metadata metadata { get; set; }

            public string firstName { get; set; }

            public string lastName { get; set; }
        }
    }
public class PeopleApiGenders
    {
        public string resourceName { get; set; }

        public string etag { get; set; }

        public List<Gender> genders { get; set; }

        public class Source
        {
            public string type { get; set; }

            public string id { get; set; }
        }

        public class Metadata
        {
            public bool primary { get; set; }

            public Source source { get; set; }
        }

        public class Gender
        {
            public Metadata metadata { get; set; }

            public string value { get; set; }
        }
var httpClient = this.httpClientFactory.CreateClient();
                string peopleApiKey = "";
                var googleAccountId = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
                var photosResponse = await httpClient.GetFromJsonAsync<PeopleApiPhotos>($"https://people.googleapis.com/v1/people/{googleAccountId}?personFields=photos&key={peopleApiKey}");
                var genderResponse = await httpClient.GetFromJsonAsync<PeopleApiGenders>($"https://people.googleapis.com/v1/people/{googleAccountId}?personFields=genders&key={peopleApiKey}");
                var namesResponse = await httpClient.GetFromJsonAsync<PeopleApiNames>($"https://people.googleapis.com/v1/people/{googleAccountId}?personFields=names&key={peopleApiKey}");

                pictureUri = photosResponse?.photos.FirstOrDefault()?.url;
                gender = genderResponse?.genders.FirstOrDefault()?.value;
                firstName = namesResponse?.names.FirstOrDefault()?.firstName;
                lastName = namesResponse?.names.FirstOrDefault()?.lastName;

相关问题