我通过自动化要求创建了简单自动化的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方案的样品,但它不适合我。因为我想实现无状态调用。
答案 0 :(得分:2)
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)]