如何在 AuthorizationOptions 中设置 FallbackPolicy 时 return HttpStatusCode 404 不正确 url?
How to return HttpStatusCode 404 for incorrect url with FallbackPolicy set in AuthorizationOptions?
在我目前正在处理的 Web 应用程序中,要求所有用户都经过身份验证。目前这是通过使用 AuthorizeFilter
.
来处理的
我现在需要能够对应用程序的不同部分应用不同的授权策略,因此我想从使用全局授权过滤器切换到设置回退策略(如官方 documentation).
这按预期工作,除了对现在不存在的资源的请求 returns HttpStatusCode 401
如果未通过身份验证,或 403
如果已通过身份验证但有一些其他要求没有实现(我们在 default/fallback 政策中有一些)。以前,使用授权过滤器解决方案,404
将被 returned。我猜原因是回退策略在管道中比授权过滤器更早被评估,但它仍然是我想避免的副作用。
(如何)我可以在使用 FallbackPolicy
时像以前一样将应用程序发送到 return 404
吗?如果应用程序使用 net5.0
(或更高版本),我想我可以使用自定义 IAuthorizationMiddlewareResultHandler
,但升级不在短期计划中,这意味着解决方案必须适用于 netcoreapp3.1
.
到 returns 404 回退策略:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapFallbackToController("api/{**slug}", nameof(ErrorController.Error404), "Error");
endpoints.MapFallbackToPage("{**slug}", "/Public/Errors/404");
});
很明显这个动作用 AllowAnonymous 装饰
[Route("api/[controller]")]
[ApiController]
public class ErrorController : ControllerBase
{
[HttpGet]
[AllowAnonymous]
public IActionResult Error404()
{
return NotFound();
}
}
对于剃刀页面:
builder.AddRazorPagesOptions(options =>
{
options.Conventions.AllowAnonymousToFolder("/Public");
政策
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireRole(LoginEntities.Sede.ToString())
.Build();
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
我在使用 netcoreapp3.1
时通过添加扩展 DenyAnonymousAuthorizationRequirement
:
的自定义授权处理程序设法获得了我想要的结果
public class CustomDenyAnonymousAuthorizationRequirement : DenyAnonymousAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DenyAnonymousAuthorizationRequirement requirement)
{
if (context.Resource != null)
{
return base.HandleRequirementAsync(context, requirement);
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
如果没有资源,此代码只是将要求标记为已满足。
像这样添加服务集合:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<IAuthorizationHandler, CustomDenyAnonymousAuthorizationRequirement>();
}
如果使用 net5.0+
,可以使用自定义 IAuthorizationMiddlewareResultHandler
来完成同样的事情:
public class CustomAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
private readonly AuthorizationMiddlewareResultHandler _defaultHandler = new();
public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
{
if ((authorizeResult.Challenged || authorizeResult.Forbidden) && context.GetEndpoint() == null)
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
await _defaultHandler.HandleAsync(next, context, policy, authorizeResult);
}
}
并添加到服务集合中:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<IAuthorizationMiddlewareResultHandler, CustomAuthorizationMiddlewareResultHandler>();
}
在我目前正在处理的 Web 应用程序中,要求所有用户都经过身份验证。目前这是通过使用 AuthorizeFilter
.
我现在需要能够对应用程序的不同部分应用不同的授权策略,因此我想从使用全局授权过滤器切换到设置回退策略(如官方 documentation).
这按预期工作,除了对现在不存在的资源的请求 returns HttpStatusCode 401
如果未通过身份验证,或 403
如果已通过身份验证但有一些其他要求没有实现(我们在 default/fallback 政策中有一些)。以前,使用授权过滤器解决方案,404
将被 returned。我猜原因是回退策略在管道中比授权过滤器更早被评估,但它仍然是我想避免的副作用。
(如何)我可以在使用 FallbackPolicy
时像以前一样将应用程序发送到 return 404
吗?如果应用程序使用 net5.0
(或更高版本),我想我可以使用自定义 IAuthorizationMiddlewareResultHandler
,但升级不在短期计划中,这意味着解决方案必须适用于 netcoreapp3.1
.
到 returns 404 回退策略:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapFallbackToController("api/{**slug}", nameof(ErrorController.Error404), "Error");
endpoints.MapFallbackToPage("{**slug}", "/Public/Errors/404");
});
很明显这个动作用 AllowAnonymous 装饰
[Route("api/[controller]")]
[ApiController]
public class ErrorController : ControllerBase
{
[HttpGet]
[AllowAnonymous]
public IActionResult Error404()
{
return NotFound();
}
}
对于剃刀页面:
builder.AddRazorPagesOptions(options =>
{
options.Conventions.AllowAnonymousToFolder("/Public");
政策
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireRole(LoginEntities.Sede.ToString())
.Build();
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
我在使用 netcoreapp3.1
时通过添加扩展 DenyAnonymousAuthorizationRequirement
:
public class CustomDenyAnonymousAuthorizationRequirement : DenyAnonymousAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DenyAnonymousAuthorizationRequirement requirement)
{
if (context.Resource != null)
{
return base.HandleRequirementAsync(context, requirement);
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
如果没有资源,此代码只是将要求标记为已满足。
像这样添加服务集合:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<IAuthorizationHandler, CustomDenyAnonymousAuthorizationRequirement>();
}
如果使用 net5.0+
,可以使用自定义 IAuthorizationMiddlewareResultHandler
来完成同样的事情:
public class CustomAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
private readonly AuthorizationMiddlewareResultHandler _defaultHandler = new();
public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
{
if ((authorizeResult.Challenged || authorizeResult.Forbidden) && context.GetEndpoint() == null)
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
await _defaultHandler.HandleAsync(next, context, policy, authorizeResult);
}
}
并添加到服务集合中:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<IAuthorizationMiddlewareResultHandler, CustomAuthorizationMiddlewareResultHandler>();
}