如何在ASP.NET Core中使用MicrosoftAccountOptions获取微软账户头像
如何在ASP.NET Core中通过MicrosoftAccountOptions获取微软账户头像
问题概述
我在ASP.NET Core应用中尝试使用MicrosoftAccountOptions获取微软账户头像,已按照外部身份验证指南构建示例应用,微软账户注册流程正常,但使用microsoftOptions.ClaimActions.MapJsonKey("photo", "picture", "url");后,AspNetUsers表并未新增相关列。同时,不清楚如何处理微软Graph中"photo"字段的类型。
当前AspNetUsers表数据示例:
sqlite> SELECT * FROM AspNetUsers; Id = ... AccessFailedCount = 0 ConcurrencyStamp = ... Email = ... EmailConfirmed = 1 LockoutEnabled = 1 LockoutEnd = NormalizedEmail = ... NormalizedUserName = ... PasswordHash = PhoneNumber = PhoneNumberConfirmed = 0 SecurityStamp = ... TwoFactorEnabled = 0 UserName = ...
相关Program.cs代码:
// ... services .AddAuthentication() .AddMicrosoftAccount(microsoftOptions => { microsoftOptions.ClientId = configuration["Authentication:Microsoft:ClientId"]; microsoftOptions.ClientSecret = configuration["Authentication:Microsoft:ClientSecret"]; //microsoftOptions.ClaimActions.MapJsonKey("photo", "picture", "url"); // ... });
解决方案
1. 添加必要的权限范围
微软账户默认权限不会返回用户头像信息,需添加User.Read权限获取用户资料:
services.AddAuthentication() .AddMicrosoftAccount(microsoftOptions => { microsoftOptions.ClientId = configuration["Authentication:Microsoft:ClientId"]; microsoftOptions.ClientSecret = configuration["Authentication:Microsoft:ClientSecret"]; // 添加User.Read权限以获取用户头像 microsoftOptions.Scope.Add("User.Read"); });
2. 正确映射头像Claim
微软Graph返回的用户头像可通过picture字段获取公开头像URL,修正Claim映射(使用标准Claim类型更规范):
microsoftOptions.ClaimActions.MapJsonKey(ClaimTypes.Photo, "picture", JsonClaimValueTypes.String);
3. 持久化头像信息到AspNetUsers表
默认外部登录的额外Claim不会自动保存到数据库,需手动处理:
步骤1:扩展IdentityUser添加自定义字段
先扩展用户实体类,新增头像URL属性:
public class ApplicationUser : IdentityUser { public string? PhotoUrl { get; set; } }
更新DbContext使用自定义用户类:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
执行EF迁移更新数据库:
dotnet ef migrations add AddPhotoUrlToUser dotnet ef database update
步骤2:在外部登录回调中保存头像信息
在处理外部登录的回调方法中,提取头像Claim并保存到用户实体:
var info = await _signInManager.GetExternalLoginInfoAsync(); if (info == null) { // 处理登录信息获取失败逻辑 } var photoClaim = info.Principal.FindFirst(ClaimTypes.Photo); if (photoClaim != null) { var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); if (user != null) { ((ApplicationUser)user).PhotoUrl = photoClaim.Value; await _userManager.UpdateAsync(user); } }
4. 直接获取头像二进制数据(可选)
若需要获取头像的二进制内容,可在OnCreatingTicket事件中调用微软Graph端点获取:
microsoftOptions.Events.OnCreatingTicket = async context => { var httpClient = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me/photo/$value"); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken); var response = await httpClient.SendAsync(request); if (response.IsSuccessStatusCode) { var photoBytes = await response.Content.ReadAsByteArrayAsync(); // 将二进制数据转为Base64字符串存储 var base64Photo = Convert.ToBase64String(photoBytes); context.Identity.AddClaim(new Claim(ClaimTypes.Photo, base64Photo)); } };
内容的提问来源于stack exchange,提问作者serdarsen
相关产品推荐
相关产品推荐

