ASP.NET Core 2.0中OpenID Connect的AdalDistributedTokenCache是什么?及Azure AD组声明实现
关于ASP.NET Core 2.0中AdalDistributedTokenCache与Azure AD组声明集成的解答
一、AdalDistributedTokenCache是什么?
AdalDistributedTokenCache是Azure AD认证库(ADAL)专为ASP.NET Core环境打造的分布式令牌缓存实现。
在单服务器部署场景下,默认的内存令牌缓存就能满足需求,但如果你的应用是多实例分布式部署(比如负载均衡后的多个节点),内存缓存就会出现令牌无法跨节点共享的问题——用户在A节点登录获取的令牌,切换到B节点请求时就找不到了,被迫重新认证。
这个组件的核心作用,就是把ADAL生成的访问令牌、刷新令牌等数据,存储到ASP.NET Core支持的分布式缓存系统中(比如Redis、SQL Server分布式缓存),让所有应用节点共享同一套令牌数据,同时自动处理令牌的过期、刷新逻辑,保证用户在分布式环境下的认证状态一致。
二、获取Azure AD用户组信息并集成到基于策略的授权步骤
下面是一步步落地你的需求的具体实现方案:
1. 配置OpenID Connect认证与必要权限
首先在Startup.cs的ConfigureServices中配置Azure AD的OpenID Connect认证,同时要确保你在Azure AD应用注册里添加了Microsoft Graph的Group.Read.All权限(需要管理员授予同意):
services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(options => { options.ClientId = "你的应用ClientId"; options.ClientSecret = "你的应用ClientSecret"; options.Authority = "https://login.microsoftonline.com/你的租户ID/v2.0"; options.ResponseType = "code id_token"; options.Scope.Add("openid"); options.Scope.Add("profile"); // 添加读取用户组的Graph权限 options.Scope.Add("https://graph.microsoft.com/Group.Read.All"); options.SaveTokens = true; // 把令牌保存到Cookie,方便后续调用Graph使用 });
2. 授权码兑换令牌+调用Graph获取组信息
在OpenID Connect的OnAuthorizationCodeReceived事件中,完成授权码兑换访问令牌、调用Graph获取用户组,再把组信息转为声明的逻辑:
options.Events = new OpenIdConnectEvents { OnAuthorizationCodeReceived = async context => { // 从回调中拿到授权码 var code = context.ProtocolMessage.Code; var credential = new ClientCredential(options.ClientId, options.ClientSecret); var authContext = new AuthenticationContext(options.Authority); // 用授权码兑换针对Microsoft Graph的访问令牌 var tokenResult = await authContext.AcquireTokenByAuthorizationCodeAsync( code, new Uri(context.Properties.Items[OpenIdConnectDefaults.RedirectUriForCodePropertiesKey]), credential, "https://graph.microsoft.com/"); // 初始化Graph客户端,用兑换到的令牌做认证 var graphClient = new GraphServiceClient( new DelegateAuthenticationProvider(request => { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.AccessToken); return Task.CompletedTask; })); // 调用Graph接口获取用户所属的组 var userGroups = await graphClient.Me.MemberOf.Request().GetAsync(); // 将组信息转为声明,添加到当前用户的身份凭证中 var claimsIdentity = context.Principal.Identity as ClaimsIdentity; foreach (var group in userGroups) { if (group is Group groupDetail) { // 这里可以用组名称作为Role声明,也可以用组ID自定义声明类型 claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, groupDetail.DisplayName)); // 示例:自定义声明类型存储组ID // claimsIdentity.AddClaim(new Claim("aad_group_id", groupDetail.Id)); } } // 把令牌存入分布式缓存(如果启用了AdalDistributedTokenCache) var distributedCache = context.HttpContext.RequestServices.GetRequiredService<IDistributedCache>(); var tokenCache = new AdalDistributedTokenCache(distributedCache, new DistributedTokenCacheOptions()); authContext.TokenCache = tokenCache; await tokenCache.SaveUserTokenCacheAsync(context.Principal, tokenResult.UserInfo.UniqueId); } };
3. 配置基于组声明的授权策略
在ConfigureServices中添加自定义授权策略,关联刚才添加的组声明:
services.AddAuthorization(options => { options.AddPolicy("RequireAdminGroup", policy => policy.RequireClaim(ClaimTypes.Role, "管理员组")); });
之后就可以在控制器或Action上使用这个策略做权限控制:
[Authorize(Policy = "RequireAdminGroup")] public IActionResult AdminDashboard() { return View(); }
4. 关键注意事项
- 必须确保Azure AD应用已经获得
Group.Read.All权限的管理员同意,否则调用Graph会返回权限不足的错误。 - 如果要启用分布式缓存,需要先配置对应的服务,比如Redis:
services.AddDistributedRedisCache(options => { options.Configuration = "你的Redis连接字符串"; options.InstanceName = "AppTokenCache"; }); - ASP.NET Core 2.0中ADAL是稳定兼容的,但如果后续有版本升级需求,可以考虑切换到MSAL(Microsoft Authentication Library)。
内容的提问来源于stack exchange,提问作者puri
相关产品推荐
相关产品推荐

