Необходимо создать настраиваемую политику, указав ее в атрибуте Authorize, который настроен на использование настраиваемого обработчика требований.
Сначала вы задаете требование настраиваемой политики через класс, который наследует IAuthorizationRequirement
public class TokenRequirement : IAuthorizationRequirement
{
}
Здесь вы можете принять параметры, если они вам нужны. Но обычно вы передаете токен в заголовке запроса, к которому обработчик требований вашей пользовательской политики будет иметь доступ без необходимости явных параметров.
Обработчик требований вашего требования, который будет использоваться вашей пользовательской политикой, будет выглядеть примерно так this
public class TokenHandler : AuthorizationHandler<TokenRequirement>
{
//Some kind of token validator logic injected into your handler via DI
private readonly TokenValidator _tokenValidator;
//The http context of this request session also injected via DI
private readonly IHttpContextAccessor _httpCtx;
//The name of the header your token can be found under on a Http Request
private const string tokenHeaderKey = "authToken";
//Constructor using DI to get a instance of a TokenValidator class you would
//have written yourself, and the httpContext
public TokenHandler(TokenValidator tokenValidator, IHttpContextAccessor httpCtx)
{
_tokenValidator = tokenValidator;
_httpCtx = httpCtx;
}
//Overriden implementation of base class AuthorizationHandler's HandleRequirementAsync method
//This is where you check your token.
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context
,TokenRequirement requirement)
{
if (context.Resource is Endpoint endpoint)
{
HttpRequest httpReqCtx = _httpCtx.HttpContext.Request;
string token =
httpReqCtx.Headers.TryGetValue(tokenHeaderKey, out StringValues tokenVal)
? tokenVal.FirstOrDefault()
: null;
if (string.IsNullOrWhitespace(token))
{
context.Fail();
}
else
{
bool tokenIsValid = await _tokenValidator.ValidToken(token);
if(tokenIsValid)
context.Succeed(requirement);
else
context.Fail();
}
}
return Task.CompletedTask;
}
}
Вы бы зарегистрировали свой обработчик пользовательских требований для имени пользовательской политики в Startup.cs, например, так:
//This is a framework extension method under Microsoft.Extensions.DependencyInjection
services.AddHttpContextAccessor();
//Your custom handler
services.AddSingleton<IAuthorizationHandler, TokenHandler>();
//Your custom policy
services.AddAuthorization(options =>
{
options.AddPolicy(
//Your custom policy's name, can be whatever you want
"myCustomTokenCheckerPolicy",
//The requirement your policy is going to check
//Which will be handled by the req handler added above
policy => policy.Requirements.Add(new TokenRequirement())
);
});
Значение атрибута будет выглядеть следующим образом
[HttpGet]
[Route("index")]
[Authorize(Policy = "myCustomTokenCheckerPolicy")]
public IActionResult Index()
{
return View();
}