В моем основном веб-API asp.net я хочу быть уверен, что пользователи действительно существуют и не деактивируются при вызове некоторых действий. Мы используем аутентификацию JwtBearer, что работает довольно хорошо. Наша проблема заключается в том, что при использовании только Microsoft.AspNetCore.Authorization.AuthorizeAttribute
не имеет значения, был ли пользователь удален или деактивирован после выдачи токена (если токен сам по себе действителен).
В моем Startup.cs
я настроил политику для решения этой проблемы:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = AuthenticationHandler.TokenValidationParameters;
});
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(
JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
options.AddPolicy(nameof(ExistingUserRequirement),
policy => policy.Requirements.Add(new ExistingUserRequirement()));
});
services.AddTransient<IAuthorizationHandler, ExistingUserHandler>();
Там я запрашиваю DataContext, если пользователь существует и активен.
Что работает:
Если я настрою атрибут Authorization
для действия, все будет работать нормально:
[HttpPost]
[Authorize(Policy = nameof(ExistingUserRequirement))]
public JsonResult Post([FromBody]CreateStoryViewModel viewModel) { ...}
Я могу получить доступ к идентификационной информации пользователя, используя HttpContextAccessor.HttpContext.User.Identity.Name
.
Что не работает: Если я настраиваю атрибут на моем BaseController
, при запуске ExistingUserHandler
контекст Identity-контекста кажется отсутствующим:
[Authorize(Policy = nameof(ExistingUserRequirement))]
public abstract class BaseController : Controller { ... }
Теперь Identity.Name возвращается всегда NULL
:
public class ExistingUserHandler : AuthorizationHandler<ExistingUserRequirement>
{
private IHttpContextAccessor HttpContextAccessor { get; }
private SaycleContext SaycleContext { get; }
public ExistingUserHandler(IHttpContextAccessor httpContextAccessor, SaycleContext saycleContext)
{
HttpContextAccessor = httpContextAccessor;
SaycleContext = saycleContext;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext authorizationContext, ExistingUserRequirement requirement)
{
var exists = false;
if (Guid.TryParse(HttpContextAccessor.HttpContext.User.Identity.Name, out var currentUserId))
{
exists = SaycleContext.Users.Any(u => Equals(u.Id, currentUserId));
}
if (!exists)
{
throw new NonExistingUserException();
}
authorizationContext.Succeed(requirement);
return Task.CompletedTask;
}
}
Я что-то упустил? Почему контекст идентичности не может быть разрешен с помощью атрибута Authorize
моего родителя BaseController
?