ASP.NET Core 中失败的授权要求的错误状态代码
Wrong status code for failed autorization requirement in ASP.NET Core
我通过自动化要求创建了具有简单自动化的网络 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]
并按预期获得了 401 Unauthorized
。但这是使用资源过滤器的糟糕方式。
我的需求实现有什么问题?为什么我得到 500 而不是 401(或 403)?
编辑: 我在日志中找到了 InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.
。
我看到了带有 cookies 方案的示例,但它不适合我。因为我要实现无状态调用。
poke 的通讯指出我以错误的方式实现了我的功能。我试图处理授权级别的安全检查,但我必须在身份验证级别上进行。所以我的最终代码看起来像:
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
中 class:
services.AddAuthentication(options => options.AddScheme(SchemeName, o => o.HandlerType = typeof(TestHandler)));
并且授权属性看起来像 [Authorize(AuthenticationSchemes = SchemeName)]
我通过自动化要求创建了具有简单自动化的网络 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]
并按预期获得了 401 Unauthorized
。但这是使用资源过滤器的糟糕方式。
我的需求实现有什么问题?为什么我得到 500 而不是 401(或 403)?
编辑: 我在日志中找到了 InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.
。
我看到了带有 cookies 方案的示例,但它不适合我。因为我要实现无状态调用。
poke 的通讯指出我以错误的方式实现了我的功能。我试图处理授权级别的安全检查,但我必须在身份验证级别上进行。所以我的最终代码看起来像:
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
中 class:
services.AddAuthentication(options => options.AddScheme(SchemeName, o => o.HandlerType = typeof(TestHandler)));
并且授权属性看起来像 [Authorize(AuthenticationSchemes = SchemeName)]