You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,
                }
            });
    }
}

关键说明

  1. 托管身份启用:确保你的应用部署在支持托管身份的Azure服务(如App Service、VM、Function等),并已为应用启用系统分配或用户分配的托管身份。
  2. 权限配置:在Azure AD中,为托管身份授予目标资源(如Microsoft Graph)的相应应用权限或委派权限。
  3. 异步支持:MSAL的方法均为异步,因此将AuthorizationCodeReceived改为异步委托(添加async关键字),原代码的Task.FromResult(0)可直接替换为异步调用。
  4. 令牌缓存:示例中复用了原有的ADALTokenCache,你也可以迁移到MSAL原生的令牌缓存实现,提升缓存效率。

内容的提问来源于stack exchange,提问作者Veena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 05:27:02