我已通过本教程在我的 ASP.NET Core 应用程序中实现了 Okta 身份验证:
https://developer.okta.com/blog/2022/04/20/dotnet-6-web-api
这非常适合我的 SPA 通过我的 api 进行身份验证。但是,有不同的用户类型可以访问我的 API,并且此信息在声明中传递。我正在尝试创建一个过滤器,以便非常容易地为我想要访问的每个端点实现。我创建了一个通用过滤器,它工作得很好,但我没有传递任何参数:
public class OktaAuthorizeFilter : IAuthorizationFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly Okta.IJwtValidator _validationService;
public OktaAuthorizeFilter(IHttpContextAccessor httpContextAccessor, IJwtValidator validationService)
{
_httpContextAccessor = httpContextAccessor;
_validationService = validationService;
}
public async void OnAuthorization(AuthorizationFilterContext context)
{
var authToken = _httpContextAccessor.HttpContext!.Request.Headers["Authorization"].ToString();
if (String.IsNullOrEmpty(authToken))
{
context.Result = new UnauthorizedObjectResult(string.Empty);
return;
}
var validatedToken = await _validationService.ValidateToken(authToken.Split(" ")[1]);
if (validatedToken == null)
{
context.Result = new UnauthorizedObjectResult(string.Empty);
return;
}
}
}
public class OktaAuthorizeAttribute : TypeFilterAttribute
{
public OktaAuthorizeAttribute() : base(typeof(OktaAuthorizeFilter))
{
}
}
这非常有效,如下所示:
[HttpGet(Name = "GetUserAccount")]
[OktaAuthorizeAttribute]
[EnableRateLimiting("api")]
public IActionResult Get()
{
UserAccount TestAccount = new UserAccount() {InternalUserNumber = 3, EmailAddress = "[email protected]"};
var json = _userAccountService.Read(TestAccount);
return Ok(json);
}
为了区分我的用户类型,Okta JWT 令牌有一个列出用户类型的声明。用户可以是 Type1 和 Type2,或者只是 Type1,等等。所以我希望实现我的过滤器,类似于 ms graph 的工作方式,如下所示:
[OktaAuthorizeAttribute(Type = new string[] { "Type1", "Type2" })]
这样,如果用户满足这些选项之一,那么它就会起作用。但是我不确定如何将参数传递给过滤器以使其工作,然后如何使用它们?这个级别的授权可以吗?
这里几乎没有什么需要更改的 - 您可以使用
HttpContext.RequestServices
中的 AuthorizationFilterContext
来解决依赖关系,因此无需注入 IHttpContextAccessor
,因为您已经拥有 HttpContext
。
您可以像这样将参数传递给您的属性:
public class OktaAuthorizeFilter : IAuthorizationFilter
{
public string[] Type;
private readonly Okta.IJwtValidator _validationService;
public OktaAuthorizeFilter()
{
}
public async void OnAuthorization(AuthorizationFilterContext context)
{
var authToken = context.HttpContext!.Request.Headers["Authorization"].ToString();
if (String.IsNullOrEmpty(authToken))
{
context.Result = new UnauthorizedObjectResult(string.Empty);
return;
}
_validationService = context.HttpContext.RequestServices.GetService<Okta.IJwtValidator>();
var validatedToken = await _validationService.ValidateToken(authToken.Split(" ")[1]);
if (validatedToken == null)
{
context.Result = new UnauthorizedObjectResult(string.Empty);
return;
}
}
}
然后就可以使用了:
[OktaAuthorizeAttribute(Items = ["Type1", "Type2"])]
不确定为什么要使用
IAuthorizationFilter
,因为 AuthorizationHandler
的使用如此灵活 - 也许将来需要考虑。 文档