简体   繁体   English

如何使用 ASP.Net Core Identity 从登录用户检索 Google 个人资料图片?

[英]How to retrieve Google profile picture from logged in user with ASP.Net Core Identity?

Ok... I'm currently using ASP.Net Core 1.1.2 with ASP.NET Core Identity 1.1.2.好的...我目前正在使用 ASP.NET Core 1.1.2 和 ASP.NET Core Identity 1.1.2。

The important part in Startup.cs looks like this: Startup.cs 中的重要部分如下所示:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        //...
        app.UseGoogleAuthentication(new GoogleOptions
        {
            AuthenticationScheme = "Google",
            SignInScheme = "Identity.External", // this is the name of the cookie middleware registered by UseIdentity()
            ClientId = Configuration["ExternalLoginProviders:Google:ClientId"],
            ClientSecret = Configuration["ExternalLoginProviders:Google:ClientSecret"]
        });
    }

GoogleOptions comes with Microsoft.AspNetCore.Authentication.Google nuget package. GoogleOptions 带有 Microsoft.AspNetCore.Authentication.Google nuget 包。

The callback function in AccountController.cs looks like this: AccountController.cs 中的回调函数如下所示:

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
    {
        //... SignInManager<User> _signInManager; declared before
        ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();
        SignInResult signInResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
        string email = info.Principal.FindFirstValue(ClaimTypes.Email);
        string firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
        string lastName = info.Principal.FindFirstValue(ClaimTypes.Surname);
        //
    }

So, everything works fine until this point.所以,到目前为止一切正常。 And here I'm stuck.我被困在这里。 I read a lot of articles about accesstokens and claims called pictureUrl and so on.我阅读了很多关于访问令牌和声明的文章,称为 pictureUrl 等。 But the Principal doesn't contain any of those.但是 Principal 不包含任何这些。

So the question is: How to retrieve the profile image once in the ExternalLoginCallback function?所以问题是:如何在 ExternalLoginCallback 函数中检索一次个人资料图像?

I struggled with the same problem but on ASP.NET Core 2.0.我在 ASP.NET Core 2.0 上遇到了同样的问题。 There is a better aproach to retrieve the picture from the OnCreatingTicket event in your startup.cs .有一种更好的方法可以从startup.csOnCreatingTicket事件中检索图片。 In your case you have to add the specific claim "picture" to the identity.在您的情况下,您必须将特定声明“图片”添加到身份中。

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddAuthentication()
            .AddCookie()
            .AddGoogle(options =>
            {
                options.ClientId = Configuration["Google.LoginProvider.ClientId"];
                options.ClientSecret = Configuration["Google.LoginProvider.ClientKey"];
                options.Scope.Add("profile");
                options.Events.OnCreatingTicket = (context) =>
                {
                    context.Identity.AddClaim(new Claim("image", context.User.GetValue("image").SelectToken("url").ToString()));

                    return Task.CompletedTask;
                };
            });
    }

Then in your AccountController you can select the image from the external login info method.然后在您的 AccountController 中,您可以从外部登录信息方法中选择图像。

var info = await _signInManager.GetExternalLoginInfoAsync();

var picture = info.Principal.FindFirstValue("image");

For .net core 3.0+, Microsoft uses System.Text.Json for handling returned object from google, so we need to use GetProperty method of this new API to get picture.对于.net core 3.0+,微软使用System.Text.Json来处理google返回的对象,所以我们需要使用这个新API的GetProperty方法来获取图片。

https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/ https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/

services.AddAuthentication()
                .AddGoogle(options =>
                {
                    IConfigurationSection googleAuthNSection = Configuration.GetSection("Authentication:Google");

                    options.ClientId = googleAuthNSection["ClientId"];
                    options.ClientSecret = googleAuthNSection["ClientSecret"];
                    options.Scope.Add("profile");
                    options.Events.OnCreatingTicket = (context) =>
                    {                      
                        var picture = context.User.GetProperty("picture").GetString();

                        context.Identity.AddClaim(new Claim("picture", picture));

                        return Task.CompletedTask;
                    };
                });

Google is starting to shut down Google+ Signin for applications as early as January 28th 2019.谷歌最早将于 2019 年 1 月 28 日开始关闭应用程序的 Google+ 登录。

https://github.com/aspnet/AspNetCore/issues/6486 https://github.com/aspnet/AspNetCore/issues/6486

So we have to do following changes to accepted answer by @mtrax :因此,我们必须对@mtrax 接受的答案进行以下更改:

.AddGoogle(o =>
            {
                o.ClientId = Configuration["Authentication:Google:ClientId"];
                o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
                o.UserInformationEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
                o.ClaimActions.Clear();
                o.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
                o.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
                o.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
                o.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
                o.ClaimActions.MapJsonKey("urn:google:profile", "link");
                o.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
                o.ClaimActions.MapJsonKey("image", "picture");
            });

I found no way to get the picture url from the claims.我发现无法从声明中获取图片网址。 Finally I found a solution using the nameidentifier, which comes with the claims.最后,我找到了一个使用 nameidentifier 的解决方案,它随声明一起提供。

string googleApiKey = "{your google api key}";
ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();
string nameIdentifier = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
string jsonUrl = $"https://www.googleapis.com/plus/v1/people/{nameIdentifier}?fields=image&key={googleApiKey}";
using (HttpClient httpClient = new HttpClient())
{
    string s = await httpClient.GetStringAsync(jsonUrl);
    dynamic deserializeObject = JsonConvert.DeserializeObject(s);
    string thumbnailUrl = (string)deserializeObject.image.url;
    byte[] thumbnail = await httpClient.GetByteArrayAsync(thumbnailUrl);
}

All you need is a Google API key.您只需要一个 Google API 密钥。

To create an API key:要创建 API 密钥:

  1. Go to the Google API Console.转到 Google API 控制台。
  2. From the project drop-down, select a project , or create a new one.从项目下拉列表中,选择一个项目,或创建一个新项目。
  3. Enable the Google+ API service:启用 Google+ API 服务:

a. a. In the list of Google APIs, search for the Google+ API service.在 Google API 列表中,搜索 Google+ API 服务。

b.Select Google+ API from the results list.从结果列表中选择 Google+ API。

c. C. Press the Enable API button.按启用 API 按钮。

When the process completes, Google+ API appears in the list of enabled APIs.该过程完成后,Google+ API 会出现在启用的 API 列表中。 To access, select APIs & Services on the left sidebar menu, then select the Enabled APIs tab.要访问,请在左侧边栏菜单中选择 API 和服务,然后选择启用的 API 选项卡。

  1. In the sidebar under "APIs & Services", select Credentials.在“API 和服务”下的侧边栏中,选择凭据。
  2. In the Credentials tab, select the New credentials drop-down list, and choose API key.在凭据选项卡中,选择新凭据下拉列表,然后选择 API 密钥。
  3. From the Create a new key pop-up, choose the appropriate kind of key for your project: Server key, Browser key, Android key, or iOS key.从“创建新密钥”弹出窗口中,为您的项目选择合适的密钥类型:服务器密钥、浏览器密钥、Android 密钥或 iOS 密钥。
  4. Enter a key Name, fill in any other fields as instructed, then select Create.输入密钥名称,按照说明填写任何其他字段,然后选择创建。

https://developers.google.com/+/web/api/rest/oauth https://developers.google.com/+/web/api/rest/oauth

You can provide additional scopes you want to request in die GoogleOptions setup.您可以在GoogleOptions设置中提供您想要请求的其他范围。 The scope you are looking for is the profile scope, grating access to the firstname, lastname and profile picture via additional claims: https://developers.google.com/identity/protocols/OpenIDConnect#discovery您正在寻找的范围是profile范围,通过附加声明可以访问名字、姓氏和个人资料图片: https : //developers.google.com/identity/protocols/OpenIDConnect#discovery

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        //...
        app.UseGoogleAuthentication(new GoogleOptions
        {
            AuthenticationScheme = "Google",
            SignInScheme = "Identity.External", // this is the name of the cookie middleware registered by UseIdentity()
            ClientId = Configuration["ExternalLoginProviders:Google:ClientId"],
            ClientSecret = Configuration["ExternalLoginProviders:Google:ClientSecret"]});
            Scopes = { "profile" };
    }

Then you can retrieve the picture claim in the controller after the authentication succeeds:然后你可以在认证成功后在控制器中检索图片声明:

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
    {
        //... SignInManager<User> _signInManager; declared before
        ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();
        SignInResult signInResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
        string email = info.Principal.FindFirstValue(ClaimTypes.Email);
        string firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
        string lastName = info.Principal.FindFirstValue(ClaimTypes.Surname);

        // profile claims
        string picture = info.Principal.FindFirstValue("picture");
        string firstName = info.Principal.FindFirstValue("given_name");
        string lastName = info.Principal.FindFirstValue("family_name");
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 ASP.Net Core Identity 从登录用户处检索 Facebook 个人资料图片? - How to retrieve Facebook profile picture from logged in user with ASP.Net Core Identity? 如何使用 ASP.Net Core Identity 3.1 从 controller 中的登录用户获取 Google 和 Facebook 个人资料图片? - How can I get Google and Facebook profile picture from logged in user in a controller with ASP.Net Core Identity 3.1? ASP.NET CORE 5.0 Identity 显示当前登录用户 - ASP.NET CORE 5.0 Identity Display current logged in user ASP.NET Core Identity 中删除登录用户的策略 - Strategies for deleting a logged-in user in ASP.NET Core Identity ASP.NET 核心 MVC 身份 - 如何查看当前登录的用户? - ASP.NET Core MVC Identity - how to get current logged in user in view? ASP.NET 核心 Web API - 如何 ZE0626222614BDEE31951D84C64E5E 使用基于登录用户角色的 DBEE31951D84C64E5E 身份登录用户角色 - ASP.NET Core Web API - How to Select Records based on logged in user role using DB Identity 如何在 ASP.NET Core Identity 中控制器的构造函数中获取登录用户名 - How to get logged-in user name in the constructor of a controller in ASP.NET Core Identity ASP.Net Core 身份和配置文件数据 - ASP.Net Core Identity and Profile Data ASP.NET MVC身份Google通过GetExternalLoginInfo提供的AccessToken访问用户配置文件 - ASP.NET MVC Identity Google access user profile via AccessToken given from GetExternalLoginInfo ASP.NET身份-如何仅允许访问已登录的用户? - ASP.NET Identity - How to allow access to ONLY the logged in User?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM