我正在探索 .Net 6 中的最小 API,并尝试将自定义授权过滤器应用于端点(通过属性或扩展)。
但在我看来,我做错了什么,或者它根本就不是设计成那样工作的(如果是这样的话,我很难过)。
除了 default usage 之外,在文档中找不到任何内容最小 API 中的 [Authorize]
属性。
这是过滤器
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : Attribute, IAuthorizationFilter
{
//Checking tokens
}
如果我尝试在 Controller 级别应用它,它工作正常
[CustomAuthorize]
public class CustomController : ControllerBase
{
//Necessary routing
}
但是如果我切换到 Minimap APIs 表示法并尝试使用属性
app.MapGet("/customEndpoint",
[CustomAuthorize] async ([FromServices] ICustomService customService, Guid id) =>
await customService.GetCustomStuff(id));
甚至是扩展方法
app.MapGet("/customEndpoint",
async ([FromServices] ICustomService customService, Guid id) =>
await customService.GetCustomStuff(id)).WithMetadata(new CustomAuthorizeAttribute());
它只是行不通。过滤器甚至没有构建。
我错过了什么或做错了什么? 提前致谢
最佳答案
您可以在 .NET 6.0 中为 Minimal API 编写自定义授权过滤器
这是我倾向于使用的方法 - 通过使用 Policy-based authorization in ASP.NET Core
需求实现IAuthorizationRequirement
public class AdminRoleRequirement : IAuthorizationRequirement
{
public AdminRoleRequirement(string role) => Role = role;
public string Role { get; set; }
}
注意:需求不需要有数据或属性。
需求处理程序实现 AuthorizationHandler<T>
public class AdminRoleRequirementHandler : AuthorizationHandler<AdminRoleRequirement>
{
public AdminRoleRequirementHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
if (context.User.HasClaim(c => c.Value == requirement.Role))
{
context.Succeed(requirement);
}
else
{
_httpContextAccessor.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
_httpContextAccessor.HttpContext.Response.ContentType = "application/json";
await _httpContextAccessor.HttpContext.Response.WriteAsJsonAsync(new { StatusCode = StatusCodes.Status401Unauthorized, Message = "Unauthorized. Required admin role." });
await _httpContextAccessor.HttpContext.Response.CompleteAsync();
context.Fail();
}
}
private readonly IHttpContextAccessor _httpContextAccessor;
}
备注:HandleRequirementAsync
方法不返回任何值。通过调用 context.Succeed(IAuthorizationRequirement requirement)
指示成功或失败的状态并通过已成功验证的要求或通过调用 context.Fail()
表示AuthorizationHandlerContext.HasSucceeded
永远不会返回 true,即使满足所有要求。
builder.Services.AddAuthorization(o =>
{
o.AddPolicy("AMIN", p => p.AddRequirements(new AdminRoleRequirement("AMIN")));
});
builder.Services.AddSingleton<IAuthorizationHandler, AdminRoleRequirementHandler>();
app.MapGet("/helloworld", () => "Hello World!").RequireAuthorization("AMIN");
https://stackoverflow.com/questions/73219729/