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

如何为ASP.NET Core 8的OData $metadata等端点强制身份验证?

解决ASP.NET Core 8 OData端点(含$metadata)未触发身份验证的问题

你的问题核心在于:OData的基础路由(比如/api/odata/$metadata)是由OData中间件直接处理的,不会经过你写的SearchController,所以控制器上的[Authorize]属性对这些请求无效,只有控制器内的接口方法会受该属性约束。下面是几种可行的解决方法:

方案1:全局应用授权策略(推荐)

通过配置全局 fallback 授权策略,让所有端点默认要求认证,仅对/login放开匿名访问。这种方式最简洁,能覆盖所有OData路由和普通API路由。

修改Program.cs:

// 先配置你的认证服务(比如JWT)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 你的JWT配置
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            // 其他参数...
        };
    });

// 配置全局授权策略:默认要求已认证用户
services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

// 继续配置OData
services.AddOData(opt =>
    opt.AddRouteComponents("/api/odata", GetEdmModel())
       .Select().Filter().OrderBy()
);

// 管道配置顺序不能错:认证→授权→端点映射
app.UseAuthentication();
app.UseAuthorization();

// 映射控制器,同时给/login添加匿名访问权限
app.MapControllers();
app.MapPost("/login", (LoginRequest req) =>
{
    // 你的登录逻辑
    return Results.Ok(new { Token = "your-jwt-token" });
}).AllowAnonymous();

方案2:为OData路由单独添加授权

如果不想全局强制认证,可以给OData路由组件单独绑定授权检查:

方法A:通过路由组件配置添加授权中间件

services.AddOData(opt =>
    opt.AddRouteComponents("/api/odata", GetEdmModel(), services =>
    {
        // 给OData路由注入授权中间件
        services.AddMiddleware<AuthorizationMiddleware>();
    })
    .Select().Filter().OrderBy()
);

方法B:通过端点路由显式要求授权

// 在Program.cs的端点配置部分,替换原有的MapControllers
app.MapODataRoute("odataRoute", "/api/odata", GetEdmModel())
   .RequireAuthorization();

// 普通控制器路由单独配置,给/login放开匿名
app.MapControllers().RequireAuthorization();
app.MapPost("/login", (LoginRequest req) => { ... }).AllowAnonymous();

方案3:自定义中间件拦截OData请求

如果以上方案不符合你的需求,可以写一个自定义中间件,在OData处理请求前检查用户认证状态:

  1. 创建中间件类:
public class ODataAuthMiddleware
{
    private readonly RequestDelegate _next;

    public ODataAuthMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 判断当前请求是否是OData路由
        if (context.Request.Path.StartsWithSegments("/api/odata"))
        {
            // 检查用户是否已认证
            if (!context.User.Identity.IsAuthenticated)
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                await context.Response.WriteAsync("Unauthorized");
                return;
            }
        }

        // 继续处理请求
        await _next(context);
    }
}
  1. 在Program.cs中注册该中间件(要放在OData相关中间件之前):
app.UseMiddleware<ODataAuthMiddleware>();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
// 其他管道配置...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 12:43:18