如何在.NET Framework 4.7 ASP.NET Web API单个端点应用Microsoft Identity Platform认证
问题描述
我有一个基于.NET Framework 4.7.2构建的遗留ASP.NET Web API应用,目前未实现任何认证机制。我希望仅为该应用的一个端点而非整个应用配置Microsoft Identity Platform认证/授权。
我已创建另一个.NET 6.0 ASP.NET Core Web API应用,其Startup.ConfigureServices方法中包含以下代码:
JwtSecurityTokenHandler.DefaultMapInboundClaims = false; services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(_configuration); services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options => { // The claim in the Jwt token where App roles are available. options.TokenValidationParameters.RoleClaimType = "roles"; });
该新应用运行正常,现在我尝试从该新应用向遗留应用发送已认证API请求,希望遗留端点处理认证,寻求正确实现方法。此前找到的相关问题未能解决我的需求。
解决方案
针对.NET Framework 4.7.2的Web API单个端点配置Microsoft Identity Platform JWT认证,按以下步骤操作:
1. 安装必要的NuGet包
在遗留项目中安装以下包:
Install-Package Microsoft.Owin.Security.Jwt Install-Package System.IdentityModel.Tokens.Jwt Install-Package Microsoft.IdentityModel.Protocols.OpenIdConnect
2. 为特定端点配置认证逻辑
方式一:Owin中间件路由匹配(推荐)
如果你的Web API基于Owin,可通过MapWhen仅对目标路由启用认证中间件,不影响其他端点:
using Microsoft.Owin; using Owin; using Microsoft.Owin.Security.Jwt; using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols; [assembly: OwinStartup(typeof(YourLegacyApi.Startup))] namespace YourLegacyApi { public class Startup { public void Configuration(IAppBuilder app) { // 仅匹配目标端点路由 app.MapWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api/protected-endpoint")), subApp => { var tenantId = "你的Azure AD租户ID"; var apiClientId = "遗留API在Azure AD的应用ID"; var authority = $"https://login.microsoftonline.com/{tenantId}/v2.0"; // 自动获取Azure AD的签名密钥 var configManager = new ConfigurationManager<OpenIdConnectConfiguration>( $"{authority}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever()); subApp.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions { AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active, TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = authority, ValidateAudience = true, ValidAudience = apiClientId, ValidateLifetime = true, RoleClaimType = "roles", // 和.NET 6应用保持一致 IssuerSigningKeyResolver = async (token, securityToken, kid, parameters) => { var config = await configManager.GetConfigurationAsync(CancellationToken.None); return config.SigningKeys.Where(k => k.KeyId == kid); } } }); }); // 保留原有Web API配置 var apiConfig = new HttpConfiguration(); WebApiConfig.Register(apiConfig); app.UseWebApi(apiConfig); } } }
方式二:Action内手动验证Token(轻量场景)
如果不想配置Owin中间件,可直接在目标Action内完成Token验证:
using System.IdentityModel.Tokens.Jwt; using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols; [RoutePrefix("api/protected")] public class ProtectedController : ApiController { private readonly IConfigurationManager<OpenIdConnectConfiguration> _configManager; private readonly string _authority = "https://login.microsoftonline.com/你的租户ID/v2.0"; private readonly string _audience = "遗留API的Azure AD应用ID"; public ProtectedController() { _configManager = new ConfigurationManager<OpenIdConnectConfiguration>( $"{_authority}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever()); } [HttpGet] public async Task<IHttpActionResult> ProtectedEndpoint() { // 提取请求头中的Bearer Token var authHeader = Request.Headers.Authorization; if (authHeader == null || !authHeader.Scheme.Equals("Bearer", StringComparison.OrdinalIgnoreCase)) { return Unauthorized(); } var token = authHeader.Parameter; var config = await _configManager.GetConfigurationAsync(CancellationToken.None); var validationParams = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = _authority, ValidateAudience = true, ValidAudience = _audience, ValidateLifetime = true, RoleClaimType = "roles", IssuerSigningKeys = config.SigningKeys }; try { var handler = new JwtSecurityTokenHandler(); handler.ValidateToken(token, validationParams, out var validatedToken); // 验证通过,可从validatedToken中获取用户/角色信息 var jwtToken = (JwtSecurityToken)validatedToken; var userRoles = jwtToken.Claims.Where(c => c.Type == "roles").Select(c => c.Value); return Ok("认证成功,已访问受保护端点"); } catch (SecurityTokenException) { return Unauthorized(); } } }
3. 启用端点授权
在目标Action上添加[Authorize]特性,确保未认证请求被拦截:
[Authorize] [HttpGet] public IHttpActionResult ProtectedEndpoint() { // ... }
4. Azure AD配置要点
- 为遗留API创建Azure AD应用注册,暴露API范围,并将该范围授权给.NET 6应用注册(需管理员同意)
- 确保Token的
aud字段匹配遗留API的应用ID或API URI - 如果需要角色权限,在遗留API的应用注册中添加应用角色,并分配给.NET 6应用或用户
5. 测试请求
从.NET 6应用发送请求时,需在请求头中携带:
Authorization: Bearer {从Microsoft Identity Platform获取的、针对遗留API的访问令牌}
内容的提问来源于stack exchange,提问作者user21996911
相关产品推荐
相关产品推荐

