为了测试目的,我已经设置了一个简单的基于策略的授权。授权有效,因为它在处理程序内部中断。如果我将测试授权设置为通过,我就可以访问我设置为使用 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;
}
}
编辑:我最终制作了一个自定义身份验证处理程序,如下所示:
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;
}
}
它似乎有效(尽管当我实际上没有对任何内容进行身份验证时实现和使用身份验证感觉有点错误),但是当我的测试处理程序失败时,它会调用challengeasync 而不是forbidasync。根据我的理解,challengeasync 适用于您不认识用户并需要对其进行验证的情况,而 forbidasync 则适用于未经授权的使用。所以只是挠挠头。