ASP.NET Core中自动化要求失败的错误状态代码

时间:2017-09-05 20:36:33

标签: c# asp.net asp.net-core asp.net-core-webapi asp.net-core-2.0

我通过自动化要求创建了简单自动化的web api。我的要求代码如下:

public class TestRequirement : IAuthorizationRequirement { }

public class TestHandler : AuthorizationHandler<TestRequirement> {
    protected override Task
        HandleRequirementAsync(AuthorizationHandlerContext context, TestRequirement requirement) {
        //context.Succeed(requirement); --#1
        //context.Fail(); --#2
        /*if (context.Resource is AuthorizationFilterContext mvcContext) {--#3
            mvcContext.Result = new UnauthorizedResult();
        }*/
        return Task.CompletedTask;
    }
}

另外,我更新了Startup.ConfigureServices(...)

        services.AddAuthorization(o => o.AddPolicy("Test", p => p.Requirements.Add(new TestRequirement())));
        services.AddSingleton<IAuthorizationHandler, TestHandler>();

我向控制器添加了适当的属性:[Authorize(Policy = "Test")]

如果我取消注释块#1 - 它按预期工作(我得到我的数据)。但是当我的代码失败时(我评论#1),我得到500 Internal Server Error

然后,我试图明确地失败了要求(取消注释块#2) - 结果相同。我知道不推荐,但我想尝试。

在此之后,我尝试了更难看的解决方法,我评论了#2和未注释的块#3。我有相同的500状态代码。

为了好玩,我实现了具有相同行为的资源过滤器:

public class TestResourceFilterAttribute : Attribute, IResourceFilter
{
    public void OnResourceExecuting(ResourceExecutingContext context) {
        context.Result = new UnauthorizedResult();
    }

    public void OnResourceExecuted(ResourceExecutedContext context) {
    }
}

然后,我在控制器上使用[TestResourceFilter]替换了我的authorize属性,并按预期获得了401 Unauthorized。但这是使用资源过滤器的坏方法。

我的要求实施有什么问题?为什么我得到500而不是401(或403)?

编辑:我在日志中找到了InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.。 我看到了带有cookies方案的样品,但它不适合我。因为我想实现无状态调用。

1 个答案:

答案 0 :(得分:2)

poke的commnets指出我以错误的方式实现了我的功能。我试图处理授权级别的安全检查,但我必须在身份验证级别上执行此操作。所以我的最终代码如下:

public class TestHandlerOptions : AuthenticationSchemeOptions { }

internal class TestHandler : AuthenticationHandler<TestHandlerOptions> {
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync() {
        if (await SomeCheckAsync()) {
            var identity = new ClaimsIdentity(ClaimsName);
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), null, ClaimsName);
            return AuthenticateResult.Success(ticket);
        }

        return AuthenticateResult.Fail("Missing or malformed 'Authorization' header.");
    }
}

ConfigureServices课程的Startup中添加下一个:

services.AddAuthentication(options => options.AddScheme(SchemeName, o => o.HandlerType = typeof(TestHandler)));

授权属性看起来像[Authorize(AuthenticationSchemes = SchemeName)]