如何在ASP.NET Core MVC应用中基于Azure AD用户查询信息
实现基于Azure AD认证的用户信息查询与复用方案
1. 创建用户信息实体与查询服务
先定义数据库对应的用户实体(假设你已有类似结构),再实现一个可注入的服务类,用于从数据库获取当前认证用户的扩展信息:
// 数据库用户实体示例 public class AppUser { public string Id { get; set; } public string PreferredUsername { get; set; } public string PhoneNumber { get; set; } // 自定义权限标识,用于授权判断 public bool IsAllowedToViewRestrictedContent { get; set; } } // 可注入的当前用户信息服务 public class CurrentAppUser { private readonly AppDbContext _dbContext; private readonly ClaimsPrincipal _currentUser; private AppUser _cachedUser; public CurrentAppUser(AppDbContext dbContext, IHttpContextAccessor httpContextAccessor) { _dbContext = dbContext; _currentUser = httpContextAccessor.HttpContext?.User ?? throw new InvalidOperationException("当前无有效用户上下文"); } // 延迟加载用户信息,避免重复查询数据库 public AppUser UserInfo => _cachedUser ??= _dbContext.AppUsers .FirstOrDefault(u => u.PreferredUsername == _currentUser.FindFirstValue("preferred_username")) ?? throw new KeyNotFoundException("数据库中未找到当前用户"); // 封装授权判断逻辑 public bool IsRequirementBasedOnLookedUpInformation => UserInfo.IsAllowedToViewRestrictedContent; }
2. 注册依赖注入服务
在Program.cs中注册所需服务(保持你的Azure AD认证配置不变):
// 注册Http上下文访问器,用于获取当前请求的用户信息 builder.Services.AddHttpContextAccessor(); // 将CurrentAppUser注册为Scoped,每个请求生成一个实例 builder.Services.AddScoped<CurrentAppUser>(); // 你的Azure AD认证配置保留 builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureB2C"));
3. 在控制器中注入使用
直接在控制器构造函数中注入CurrentAppUser,即可获取用户扩展信息:
public class CashFlowAnalysisController : Controller { private readonly AppDbContext _dbContext; private readonly CurrentAppUser _currentAppUser; public CashFlowAnalysisController(AppDbContext dbContext, CurrentAppUser currentAppUser) { _dbContext = dbContext; _currentAppUser = currentAppUser; } public IActionResult Index() { // 获取用户手机号 var userPhone = _currentAppUser.UserInfo.PhoneNumber; // 判断权限 var hasAccess = _currentAppUser.IsRequirementBasedOnLookedUpInformation; return View(); } }
4. 实现自定义授权策略
创建授权需求与处理器,用于支持[Authorize]特性的策略判断:
// 授权需求类 public class UserInfoBasedRequirement : IAuthorizationRequirement { } // 授权处理器 public class UserInfoBasedRequirementHandler : AuthorizationHandler<UserInfoBasedRequirement> { private readonly CurrentAppUser _currentAppUser; public UserInfoBasedRequirementHandler(CurrentAppUser currentAppUser) { _currentAppUser = currentAppUser; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserInfoBasedRequirement requirement) { if (_currentAppUser.IsRequirementBasedOnLookedUpInformation) { context.Succeed(requirement); } return Task.CompletedTask; } }
在Program.cs中注册授权策略与处理器:
builder.Services.AddAuthorization(options => { options.AddPolicy("IsRequirementBasedOnLookedUpInformation", policy => policy.Requirements.Add(new UserInfoBasedRequirement())); }); builder.Services.AddScoped<IAuthorizationHandler, UserInfoBasedRequirementHandler>();
之后即可在控制器/Action上使用该策略:
[Authorize(Policy = "IsRequirementBasedOnLookedUpInformation")] public IActionResult RestrictedAction() { return View(); }
5. 在Razor视图中使用
在视图顶部注入CurrentAppUser,直接通过属性控制视图渲染:
@inject CurrentAppUser CurrentUser @if (CurrentUser.IsRequirementBasedOnLookedUpInformation) { <div class="authorized-content"> <p>您有权限查看此内容</p> <p>绑定手机号:@CurrentUser.UserInfo.PhoneNumber</p> </div> } else { <p>您无权限访问此内容</p> }
关键注意事项
- 你之前尝试的
IUserClaimsPrincipalFactory属于ASP.NET Identity框架组件,而你使用的是Azure AD的OpenID Connect认证,未集成Identity,因此会缺失UserManager等依赖导致报错,本方案完全基于Azure AD认证的ClaimsPrincipal,无需依赖Identity。 - 确保Azure AD返回的Claims中包含
preferred_username,若未包含,需在Azure AD应用配置中添加对应的声明映射。 CurrentAppUser采用延迟加载逻辑,仅在首次访问UserInfo时查询数据库,减少不必要的数据库请求。
内容的提问来源于stack exchange,提问作者Mister 832
相关产品推荐
相关产品推荐

