我一直在使用.net核心webapi作为后端创建角度应用程序。在我的应用程序中是一个用户管理面板,具有足够特权的用户可以在其中更改数据(电子邮件,密码,应用程序中的角色等)。我想在每次更改特定用户的数据时强制应用程序刷新身份验证令牌(但仅强制该用户刷新令牌)或将其重定向到登录页面。我希望该功能可以确保当我更改用户角色时,用户不会(或确实拥有)立即访问应用程序的某些部分。
我当前的解决方案是添加并发戳(或其中的哈希)作为声明值,然后在每个api调用期间通过实现自定义AuthorizationHandler对其进行验证。这是实现此目的的代码示例:
var claims = principal.Claims.ToList();
claims.Add(new Claim(
CustomClaimTypes.Version, userIdentity.ConcurrencyStamp));
return Ok(await _tokenGenerator.GenerateToken(userIdentity, claims));
public class ConcurrencyAuthorizationRequirement : IAuthorizationRequirement
{
}
public class ConcurrencyAuthorizationHandler : AuthorizationHandler<ConcurrencyAuthorizationRequirement>
{
private readonly UserManager<CustomIdentityUser> _userManager;
public ConcurrencyAuthorizationHandler(UserManager<CustomIdentityUser> userManager)
{
_userManager = userManager;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ConcurrencyAuthorizationRequirement requirement)
{
var versionClaim = context.User.Claims.FirstOrDefault(x => x.Type == CustomClaimTypes.Version);
if (versionClaim != null)
{
var concurrencyStamp = _userManager.FindByNameAsync(context.User.Identity.Name).Result.ConcurrencyStamp;
if (string.Equals(concurrencyStamp, versionClaim.Value))
{
context.Succeed(requirement);
return Task.CompletedTask;
}
}
var filterContext = context.Resource as AuthorizationFilterContext;
var response = filterContext?.HttpContext.Response;
var message = Encoding.UTF8.GetBytes("some message");
response?.OnStarting(async () =>
{
filterContext.HttpContext.Response.StatusCode = 401;
await response.Body.WriteAsync(message, 0, message.Length);
});
return Task.CompletedTask;
}
}
Angular应用程序将使用http拦截器来处理刷新令牌(与到期令牌功能相似)
它工作得很好,但是我对每个api调用中的每个数据库查询都不满意...
我的问题是: 1.我相信有更好的方法可以达到相同的结果。应该怎么做才能获得相似的结果? 2.我在使用UserManager缓存ConcurrecyStamp时遇到问题。将UserManager添加为作用域依赖项不会刷新图章。仅在将管理器声明为临时依赖项之后,它才开始工作。是什么原因呢?