Api .Net Core-基于策略的授权在授权失败时返回500

Api .Net Core-基于策略的授权在授权失败时返回500,api,asp.net-core,authorization,Api,Asp.net Core,Authorization,我已经为测试目的设置了一个简单的基于策略的授权。授权可以工作,因为它在处理程序内部中断。如果我将测试授权设置为通过,则允许我访问设置为使用TestPolicy的控制器端点。但是,如果我像下面的代码片段中那样将其设置为失败,则授权将失败,但我会得到一个500响应,显然401或403是合适的 我相当肯定这是因为API没有任何形式的身份验证。但我不想在这个API中实现任何身份验证,因为对它的所有调用都应该被视为是经过身份验证的。角色等将通过httpcontext获取。有人知道我如何解决这个问题而不需要

我已经为测试目的设置了一个简单的基于策略的授权。授权可以工作,因为它在处理程序内部中断。如果我将测试授权设置为通过,则允许我访问设置为使用TestPolicy的控制器端点。但是,如果我像下面的代码片段中那样将其设置为失败,则授权将失败,但我会得到一个500响应,显然401或403是合适的

我相当肯定这是因为API没有任何形式的身份验证。但我不想在这个API中实现任何身份验证,因为对它的所有调用都应该被视为是经过身份验证的。角色等将通过httpcontext获取。有人知道我如何解决这个问题而不需要API使用者进行身份验证吗

测试代码如下。new TestRequirement()的参数可以轻松更改为测试通过/失败授权

public static void Configure(IServiceCollection services, IConfiguration configuration)
{
     services.AddAuthorization(options =>
     {
         options.AddPolicy("TestPolicy",
            policy => policy.Requirements.Add(new TestRequirement(false)));
     });

     services.AddSingleton<IAuthorizationHandler, TestHandler>();

     //<snip>
}

public class TestHandler : AuthorizationHandler<TestRequirement>
{
    /// <inheritdoc />
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TestRequirement requirement)
    {
        if (requirement.Passes)
        {
            context.Succeed(requirement);
        }
            
        return Task.CompletedTask;
    }
}

public class TestRequirement : IAuthorizationRequirement
{
    public bool Passes { get; }

    public TestRequirement(bool shouldPass)
    {
        this.Passes = shouldPass;
    }
}
公共静态无效配置(IServiceCollection服务、IConfiguration配置)
{
services.AddAuthorization(选项=>
{
options.AddPolicy(“TestPolicy”,
policy=>policy.Requirements.Add(newtestrequirement(false));
});
services.AddSingleton();
//
}
公共类TestHandler:AuthorizationHandler
{
/// 
受保护的覆盖任务HandleRequirementAsync(授权HandlerContext上下文,TestRequirement)
{
if(要求通过)
{
成功(要求);
}
返回Task.CompletedTask;
}
}
公共类TestRequirement:IAuthorizationRequirement
{
公共布尔通行证{get;}
公共测试要求(bool shouldPass)
{
this.Passes=shouldPass;
}
}
编辑:我最终制作了一个自定义authenticationhandler,如下所示:

public class AuthenticationSchemeHandler : IAuthenticationHandler
{
    private HttpContext httpContext;

    /// <inheritdoc />
    public Task<AuthenticateResult> AuthenticateAsync()
        => Task.FromResult(AuthenticateResult.NoResult());

    /// <inheritdoc />
    public Task ChallengeAsync(AuthenticationProperties properties)
    {
        properties ??= new AuthenticationProperties();
        this.httpContext.Response.StatusCode = (int) HttpStatusCode.Unauthorized;

        return Task.CompletedTask;
    }

    /// <inheritdoc />
    public Task ForbidAsync(AuthenticationProperties properties)
    {
        properties ??= new AuthenticationProperties();
        this.httpContext.Response.StatusCode = (int) HttpStatusCode.Forbidden;

        return Task.CompletedTask;
    }

    /// <inheritdoc />
    public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
    {
        this.httpContext = context;

        return Task.CompletedTask;
    }
}
公共类AuthenticationSchemeHandler:IAAuthenticationHandler
{
私有HttpContext HttpContext;
/// 
公共任务同步()
=>Task.FromResult(AuthenticateResult.NoResult());
/// 
公共任务ChallengeAsync(AuthenticationProperties)
{
属性???=新的AuthenticationProperties();
this.httpContext.Response.StatusCode=(int)HttpStatusCode.Unauthorized;
返回Task.CompletedTask;
}
/// 
公共任务禁止异步(AuthenticationProperties)
{
属性???=新的AuthenticationProperties();
this.httpContext.Response.StatusCode=(int)HttpStatusCode.probled;
返回Task.CompletedTask;
}
/// 
公共任务InitializeAsync(AuthenticationScheme,HttpContext上下文)
{
this.httpContext=context;
返回Task.CompletedTask;
}
}

这似乎是可行的(虽然在我没有实际验证任何东西的情况下实现和使用身份验证感觉有点错误),但是当我的testhandler失败时,它将调用challengeasync而不是ProbleAsync。据我所知,challengeasync适用于不了解用户并需要验证的情况,而禁止Async适用于未经授权的情况。所以我只是挠头而已。

是的,你说得对。质询结果通常应用于当前访问者未登录,但试图访问需要经过身份验证的用户的操作的情况。它将提示对凭据的质询。它还可用于未经授权执行操作的经过身份验证的用户,以及您希望提示输入更高权限凭据的用户。如果当前访问者以用户身份登录您的系统,但试图访问其帐户无权执行的操作,则应使用禁止结果。@ZhiLv感谢您的确认。问题是我从来没有真正认证过任何人。因此,我想,最终它使用挑战是可以的。我只是不知道我怎么才能做出禁止触发。我还没能做到。如果策略失败且用户已通过身份验证,是否会自动发生这种情况?