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

如何将.NET Core的Azure AD/MSAL教程适配到.NET Framework项目?

ASP.NET Framework 4.7.2 适配Azure AD + MSAL 实现指南

针对你提到的.NET Core教程适配问题,ASP.NET Framework 4.7.2主要通过OWIN中间件和Web.config配置替代.NET Core中Program.cs的初始化逻辑,以下是具体步骤:

1. 安装必要的NuGet包

首先添加适配.NET Framework的身份认证相关包:

Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Microsoft.Owin.Security.OpenIdConnect
Install-Package Microsoft.Owin.Security.Cookies
Install-Package Microsoft.Identity.Client
# 可选:若想使用简化的Microsoft.Identity.Web封装,安装以下包
Install-Package Microsoft.Identity.Web.Owin

2. 迁移配置到Web.config

将.NET Core教程中appsettings.json的配置项移到Web.config的<appSettings>节点:

<appSettings>
  <add key="AzureAd:Instance" value="https://login.microsoftonline.com/" />
  <add key="AzureAd:Domain" value="your-company-domain.onmicrosoft.com" />
  <add key="AzureAd:TenantId" value="your-tenant-guid" />
  <add key="AzureAd:ClientId" value="your-app-client-id" />
  <add key="AzureAd:ClientSecret" value="your-app-client-secret" /> <!-- 或用证书替代 -->
  <add key="AzureAd:CallbackPath" value="/signin-oidc" />
  <add key="InternalApi:BaseUrl" value="https://your-internal-api-server" />
  <add key="InternalApi:Scopes" value="api://your-api-client-id/access_as_user" />
</appSettings>

3. 创建OWIN Startup类替代Program.cs逻辑

ASP.NET Framework通过OWIN的Startup类配置身份认证中间件,替代.NET Core中Program.cs的管道初始化:

using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using System.Configuration;
using Microsoft.Identity.Client;

[assembly: OwinStartup(typeof(YourProjectNamespace.Startup))]
namespace YourProjectNamespace
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // 默认使用Cookie存储认证会话
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            // 配置OpenID Connect认证(对应.NET Core中的AddOpenIdConnect)
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId = ConfigurationManager.AppSettings["AzureAd:ClientId"],
                Authority = $"{ConfigurationManager.AppSettings["AzureAd:Instance"]}{ConfigurationManager.AppSettings["AzureAd:TenantId"]}",
                RedirectUri = ConfigurationManager.AppSettings["AzureAd:CallbackPath"],
                PostLogoutRedirectUri = "/",
                Scope = "openid profile offline_access", // 包含offline_access以获取刷新令牌
                ResponseType = "code id_token",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    // 授权码接收后,获取API访问令牌
                    AuthorizationCodeReceived = async context =>
                    {
                        var confidentialClient = ConfidentialClientApplicationBuilder
                            .Create(ConfigurationManager.AppSettings["AzureAd:ClientId"])
                            .WithClientSecret(ConfigurationManager.AppSettings["AzureAd:ClientSecret"])
                            .WithAuthority(new Uri($"{ConfigurationManager.AppSettings["AzureAd:Instance"]}{ConfigurationManager.AppSettings["AzureAd:TenantId"]}"))
                            .WithRedirectUri(ConfigurationManager.AppSettings["AzureAd:CallbackPath"])
                            .Build();

                        // 兑换授权码为API访问令牌
                        var tokenResult = await confidentialClient
                            .AcquireTokenByAuthorizationCode(
                                new[] { ConfigurationManager.AppSettings["InternalApi:Scopes"] },
                                context.Code)
                            .ExecuteAsync();

                        // 将令牌存入Claims,供后续API调用使用
                        context.AuthenticationTicket.Identity.AddClaim(
                            new System.Security.Claims.Claim("api_access_token", tokenResult.AccessToken));
                    },

                    // 处理认证失败场景
                    AuthenticationFailed = context =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect($"/Error?msg={context.Exception.Message}");
                        return System.Threading.Tasks.Task.CompletedTask;
                    }
                }
            });
        }
    }
}

4. 调用内部API的示例代码

在Controller或Web Forms页面中,从Claims中取出令牌并发起API请求:

public async Task<ActionResult> CallInternalApi()
{
    var accessToken = User.Claims.FirstOrDefault(c => c.Type == "api_access_token")?.Value;
    if (string.IsNullOrEmpty(accessToken))
    {
        return RedirectToAction("Login", "Account");
    }

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
    
    var apiResponse = await client.GetAsync($"{ConfigurationManager.AppSettings["InternalApi:BaseUrl"]}/api/resource");
    if (apiResponse.IsSuccessStatusCode)
    {
        var content = await apiResponse.Content.ReadAsStringAsync();
        return View("ApiResult", content);
    }
    else
    {
        return View("Error", $"API调用失败: {apiResponse.StatusCode}");
    }
}

关键注意事项

  • 重定向URI配置:确保Azure AD应用注册中的重定向URI与Web.config里的CallbackPath一致(例如https://localhost:44300/signin-oidc)
  • 安全最佳实践:避免硬编码客户端密钥,建议使用Azure Key Vault或加密的Web.config配置
  • Web Forms适配:若项目是Web Forms,认证逻辑同样通过OWIN Startup配置,页面中可通过Context.User.Claims获取令牌

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:35:57