ADAL不支持托管身份凭证,如何改造代码实现S360安全密钥认证
改造ADAL代码以使用托管身份认证(移除应用密码)
Microsoft.IdentityModel.Clients.ActiveDirectory(ADAL)不支持托管身份认证凭证,我需要将现有代码改造为基于托管身份的实现,以此完成S360安全密钥认证并移除应用中的密码。
原代码如下:
public partial class Startup { private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; private static string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"]; private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"]; private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"]; private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"]; public static readonly string Authority = aadInstance + tenantId; // AAD Graph API的资源ID,用于请求访问令牌 string graphResourceId = "https://graph.windows.net"; public void ConfigureAuth(IAppBuilder app) { ApplicationDbContext db = new ApplicationDbContext(); app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { ClientId = clientId, Authority = Authority, PostLogoutRedirectUri = postLogoutRedirectUri, Notifications = new OpenIdConnectAuthenticationNotifications() { // 处理OpenID Connect响应中的授权码,兑换为访问令牌和刷新令牌并存储 AuthorizationCodeReceived = (context) => { var code = context.Code; ClientCredential credential = new ClientCredential(clientId, appKey); string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value; AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID)); AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode( code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId); // AccountHelper.token = result.AccessToken; return Task.FromResult(0); } }, TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters { ValidateIssuer = false, ValidAudience = clientId, } }); } }
我曾尝试按文档操作但未成功:当前代码无法使用异步操作,用Azure.Core生成的令牌也不被AuthenticationContext.AcquireTokenByAuthorizationCode方法支持。
解决方案:替换ADAL为MSAL并使用托管身份
ADAL已被官方废弃,推荐使用Microsoft Authentication Library (MSAL),它原生支持托管身份认证,且能更好地适配现代Azure身份验证场景。
步骤1:安装MSAL包
安装Microsoft.Identity.Client NuGet包,替代原有的ADAL依赖。
步骤2:修改Startup类实现
移除客户端密钥相关配置,用MSAL的托管身份支持重构授权码处理逻辑:
using Microsoft.Identity.Client; using System.Security.Claims; using System.Web; public partial class Startup { private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"]; private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"]; private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"]; public static readonly string Authority = $"{aadInstance}{tenantId}"; // 建议替换为Microsoft Graph API(AAD Graph已逐步淘汰) private static string graphResourceId = "https://graph.microsoft.com"; public void ConfigureAuth(IAppBuilder app) { ApplicationDbContext db = new ApplicationDbContext(); app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { ClientId = clientId, Authority = Authority, PostLogoutRedirectUri = postLogoutRedirectUri, Notifications = new OpenIdConnectAuthenticationNotifications() { AuthorizationCodeReceived = async (context) => { var code = context.Code; var redirectUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)); // 使用托管身份构建机密客户端应用 var confidentialClient = ConfidentialClientApplicationBuilder .Create(clientId) .WithAuthority(Authority) .WithRedirectUri(redirectUri.ToString()) .WithManagedIdentity() // 启用托管身份认证,无需客户端密钥 .Build(); // 获取用户唯一标识 string signedInUserId = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value; // 将用户标识关联到MSAL令牌缓存 confidentialClient.UserTokenCache.SetBeforeAccess(async args => { // 这里可以复用原有的ADALTokenCache逻辑,或者迁移到MSAL的缓存实现 var cache = new ADALTokenCache(signedInUserId); args.TokenCache.DeserializeMsalV3(cache.Serialize()); }); // 兑换授权码获取访问令牌 var result = await confidentialClient.AcquireTokenByAuthorizationCode( new[] { $"{graphResourceId}/.default" }, code) .ExecuteAsync(); // AccountHelper.token = result.AccessToken; } }, TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters { ValidateIssuer = false, ValidAudience = clientId, } }); } }
关键说明
- 托管身份启用:确保你的应用部署在支持托管身份的Azure服务(如App Service、VM、Function等),并已为应用启用系统分配或用户分配的托管身份。
- 权限配置:在Azure AD中,为托管身份授予目标资源(如Microsoft Graph)的相应应用权限或委派权限。
- 异步支持:MSAL的方法均为异步,因此将
AuthorizationCodeReceived改为异步委托(添加async关键字),原代码的Task.FromResult(0)可直接替换为异步调用。 - 令牌缓存:示例中复用了原有的
ADALTokenCache,你也可以迁移到MSAL原生的令牌缓存实现,提升缓存效率。
内容的提问来源于stack exchange,提问作者Veena
相关产品推荐
相关产品推荐

