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

如何在C#中间件app.Map的IApplicationBuilder中设置授权策略

问题描述

我有个授权策略在如下简单端点中能正常工作:

app.Map("/test", () => "hi").RequireAuthorization("WebAPI");

现在希望在使用IApplicationBuilder的app.Map("/proxy", Handle)中实现相同的授权效果,相关代码如下:

public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
    builder.Services.AddAuthentication()
        .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

    builder.Services.AddAuthorization(options =>
    {
        options.AddPolicy("WebAPI", new AuthorizationPolicyBuilder(OpenIdConnectDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser()
            .Build());
        options.FallbackPolicy = new AuthorizationPolicyBuilder(OpenIdConnectDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser()
            .Build();
        
        options.DefaultPolicy = options.GetPolicy("WebAPI")!;
    });
    
    builder.Services.AddControllers();

    builder.Services.AddHttpForwarder();

    var app = builder.Build();

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();
    
    app.UseAuthentication();
    app.UseAuthorization();

    app.Map("/test", () => "hi").RequireAuthorization("WebAPI");  // 此处授权正常工作
    app.Map("/proxy", Handle); // 此处授权不生效

    app.MapControllers();

    app.Run();
}

private static void Handle(IApplicationBuilder app)
{
    app.Run(async httpContext =>
    {
        if (httpContext.User.Identity is { IsAuthenticated: false })
        {
            httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            await httpContext.Response.WriteAsync("Unauthorized");
            return;
        }
        
        httpContext.Response.StatusCode = 200;
        await httpContext.Response.WriteAsync("Hello");
    });
}
解决方案

你可以通过两种方式给/proxy端点加上相同的WebAPI授权策略:

方法一:直接在Map时添加授权约束

和/test端点的写法一致,直接在Map后链式调用RequireAuthorization,框架会自动处理授权逻辑,只有通过授权的请求才会进入Handle方法:

app.Map("/proxy", Handle).RequireAuthorization("WebAPI");

修改后Handle方法可以简化,不需要手动判断认证状态:

private static void Handle(IApplicationBuilder app)
{
    app.Run(async httpContext =>
    {
        httpContext.Response.StatusCode = 200;
        await httpContext.Response.WriteAsync("Hello");
    });
}

方法二:在中间件内手动触发授权验证

如果需要在Handle方法内自定义授权处理逻辑,可以通过IAuthorizationService手动验证当前请求是否符合WebAPI策略:

private static void Handle(IApplicationBuilder app)
{
    app.Run(async httpContext =>
    {
        var authorizationService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
        var result = await authorizationService.AuthorizeAsync(httpContext.User, null, "WebAPI");
        
        if (!result.Succeeded)
        {
            // 根据授权失败原因返回对应状态码
            httpContext.Response.StatusCode = result.Failure?.FailureReasons.Any(r => r is DenyAuthorizationRequirement) 
                ? (int)HttpStatusCode.Forbidden 
                : (int)HttpStatusCode.Unauthorized;
            await httpContext.Response.WriteAsync("Unauthorized");
            return;
        }
        
        httpContext.Response.StatusCode = 200;
        await httpContext.Response.WriteAsync("Hello");
    });
}

注意事项

  • 确保UseAuthentication()和UseAuthorization()中间件在UseRouting()之后、端点映射之前正确配置,这是授权生效的必要前提。
  • 优先选择方法一,它复用了ASP.NET Core的内置授权管道,减少手动代码的同时也能保证逻辑的一致性。

内容的提问来源于stack exchange,提问作者Node.JS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 04:05:54