基于.NET Framework 4.8的ASP.NET Core 2.2 API Azure AD授权问题
ASP.NET Core 2.2(.NET Framework 4.8)迁移Azure AD授权解决方案
问题背景
我有一个托管在.NET Framework 4.8中的ASP.NET Core 2.2 API,采用该架构是为了直接引用传统.NET Framework构建的类库。当前API使用ADFS,现需迁移至Azure AD。已配置Swagger并可通过选择作用域完成Azure AD认证,但授权功能无法正常工作。由于Microsoft.AspNetCore包无法在.NET Framework 4.8上安装,无法在Configure()中使用app.UseAuthorization();且Microsoft.Identity.Web包要求.NET Core 3.0及以上版本,恳请协助实现Azure AD授权功能。
当前代码片段
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApiVersionDescriptionProvider provider) { app.UseStaticFiles(); app.UseAuthentication(); if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); AspNetCore.Serilog.DependencyInjection.UseIdentityLogging(app); app.UseLogging(); app.UseExceptionHandling(); app.UseMvc(); app.UseSwagger(); app.UseAzureSwaggerUi(_azureAdConfig); app.UseCors(policy => policy.WithOrigins("https://localhost:60216", "https://localhost:60216") .AllowAnyMethod() .WithHeaders(HeaderNames.ContentType) ); app.UseAuthentication(); app.UseAuthorization();//not available } public void ConfigureServices(IServiceCollection services) { //Azure ad services.AddAuthentication(AzureADDefaults.AuthenticationScheme) .AddAzureAD(options => Configuration.Bind("AzureAd", options)); services.AddAuthorization(auth => { auth.AddPolicy("AzureAD", new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(AzureADDefaults.AuthenticationScheme) .RequireAuthenticatedUser().Build()); }); services.AddSingleton<IAuthorizationHandler, RequiredRoleAuthorisationHandler>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddSwaggerOAuth2Authorization(_azureAdConfig); services.RegisterAuthorisationPolicies(); ConfigureSwagger(services); ConfigureApplicationServices(services); }
解决方案
方案1:全局添加授权过滤器替代中间件
ASP.NET Core 2.2中可通过Mvc全局过滤器实现授权逻辑,替代UseAuthorization()的作用:
services.AddMvc(options => { // 全局绑定AzureAD授权策略 var azureAdPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(AzureADDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .Build(); options.Filters.Add(new AuthorizeFilter(azureAdPolicy)); }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
方案2:自定义授权中间件
如果需要更灵活的管道控制,可手动实现授权中间件:
public class AuthorizationMiddleware { private readonly RequestDelegate _next; public AuthorizationMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context, IAuthorizationService authorizationService) { // 指定要验证的策略名称 var policyName = "AzureAD"; var authResult = await authorizationService.AuthorizeAsync(context.User, null, policyName); if (!authResult.Succeeded) { context.Response.StatusCode = StatusCodes.Status403Forbidden; return; } await _next(context); } } // 在Configure()中注册中间件,放在UseAuthentication()之后、UseMvc()之前 app.UseMiddleware<AuthorizationMiddleware>();
代码调整注意事项
- 移除
Configure()中无效的app.UseAuthorization()调用,避免编译错误 - 验证Azure AD配置参数(TenantId、ClientId等)是否通过
Configuration.Bind("AzureAd", options)正确绑定 - 确保自定义授权处理器
RequiredRoleAuthorisationHandler逻辑正确,示例实现如下:
public class RequiredRoleAuthorisationHandler : AuthorizationHandler<RoleRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement) { if (context.User.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == requirement.RequiredRole)) { context.Succeed(requirement); } return Task.CompletedTask; } } public class RoleRequirement : IAuthorizationRequirement { public string RequiredRole { get; set; } public RoleRequirement(string role) { RequiredRole = role; } }
授权验证
在控制器或Action上通过[Authorize(Policy = "AzureAD")]标记,或使用全局过滤器后,所有接口将自动应用授权策略。可通过Swagger携带Azure AD令牌调用接口,验证是否返回正确的403/200状态码。
内容的提问来源于stack exchange,提问作者Auroops
相关产品推荐
相关产品推荐

