我正在使用Blazor和.NET Core v3构建新应用程序。
作为身份验证,我想使用我们的Google G Suite。
我设法登录,但是我很难找到个人头像显示在标题中。
这是我的Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
services.AddAuthentication()
.AddGoogle("Google", options =>
{
IConfigurationSection googleAuthNSection =
Configuration.GetSection("Authentication:Google");
options.ClientId = googleAuthNSection["ClientId"];
options.ClientSecret = googleAuthNSection["ClientSecret"];
options.UserInformationEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
options.ClaimActions.Clear();
options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
options.ClaimActions.MapJsonKey("urn:google:profile", "link");
options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
options.ClaimActions.MapJsonKey("image", "picture");
options.Events = new OAuthEvents
{
OnCreatingTicket = context =>
{
var myProfile = JsonSerializer.Deserialize<Dictionary<string, object>>(context.User.ToString());
if (myProfile.ContainsKey("picture"))
{
var identity = (ClaimsIdentity)context.Principal.Identity;
identity.AddClaim(new Claim("picture", myProfile["picture"].ToString()));
}
return Task.CompletedTask;
}
};
});
}
这是我的_LoginPartial.cshtml
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.Name!</a>
</li>
<li class="nav-item">
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/", new { area = "" })" method="post">
<button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
@foreach (var claim in User.Claims)
{
<span>@claim.Type : @claim.Value</span>
}
}
我以为options.ClaimActions.MapJsonKey
会填满我的User.Claims
。但是在我的foreach
中,仅存在4个基本声明。
我知道myProfile["picture"]
保留个人资料图片的网址。但是我无法在“登录”页面上获得它。
我已经尝试过:
var info = await SignInManager.GetExternalLoginInfoAsync();
if (info != null)
{
var avatar = info.Principal.FindFirst("picture");
}
更新:myProfile
包含:
[0]: {[id, ValueKind = String : "1095252652..."]}
[1]: {[email, ValueKind = String : "paul..."]}
[2]: {[verified_email, ValueKind = True : "True"]}
[3]: {[name, ValueKind = String : "Paul.."]}
[4]: {[given_name, ValueKind = String : "Paul"]}
[5]: {[family_name, ValueKind = String : ".."]}
[6]: {[picture, ValueKind = String : "https://lh3.googleusercontent.com/a-/A..."]}
[7]: {[locale, ValueKind = String : "nl"]}
[8]: {[hd, ValueKind = String : "..."]}
本文显示了有效的代码:Google Authentication in Server Side Blazor
对startup.cs的此更改可能是您需要的:
services.AddAuthentication().AddGoogle(options =>
{
options.ClientId = Configuration["Google:ClientId"];
options.ClientSecret = Configuration["Google:ClientSecret"];
options.ClaimActions.MapJsonKey("urn:google:profile", "link");
options.ClaimActions.MapJsonKey("urn:google:image", "picture");
});
您可以使用.razor控件显示图像,如下所示:
@using System.Security.Claims
@using Microsoft.AspNetCore.Http
@inject IHttpContextAccessor _httpContextAccessor
@inject HttpClient Http
@if (User.Identity.Name != null)
{
<img src="@Avatar" />
<b>You are logged in as: @GivenName @Surname</b>
<a class="ml-md-auto btn btn-primary"
href="/Logout"
target="_top">Logout</a>
}
else
{
<a class="ml-md-auto btn btn-primary"
href="/Login"
target="_top">Login</a>
}
@code {
private ClaimsPrincipal User;
private string GivenName;
private string Surname;
private string Avatar;
protected override void OnInitialized()
{
base.OnInitialized();
try
{
// Set the user to determine if they are logged in
User = _httpContextAccessor.HttpContext.User;
// Try to get the GivenName
var givenName =
_httpContextAccessor.HttpContext.User
.FindFirst(ClaimTypes.GivenName);
if (givenName != null)
{
GivenName = givenName.Value;
}
else
{
GivenName = User.Identity.Name;
}
// Try to get the Surname
var surname =
_httpContextAccessor.HttpContext.User
.FindFirst(ClaimTypes.Surname);
if (surname != null)
{
Surname = surname.Value;
}
else
{
Surname = "";
}
// Try to get Avatar
var avatar =
_httpContextAccessor.HttpContext.User
.FindFirst("urn:google:image");
if (avatar != null)
{
Avatar = avatar.Value;
}
else
{
Avatar = "";
}
}
catch { }
}
}