本教程
Create an ASP.NET Core app with user data protected by authorization on docs.microsoft.com
教导我们使用“角色”来处理授权。
但是,关于角色,我注意到一件事:
如果在用户登录时将其添加到角色中,则更改似乎要在注销后才可见。
也就是说:如果我在登录特定的identityUser
时打电话给我,
userManager.AddToRoleAsync(idenityUser, role)
然后使用本教程中显示的操作检查当前用户是否具有角色:
context.User.IsInRole(role)
即使User
引用此特定identityUser
,也返回FALSE。并且它一直返回false,直到用户注销并再次登录。
我实际上试图在本教程中增强该应用程序以添加Promote功能,即允许管理员将常规用户提升为Manager。是的,被提升的用户必须注销后才能登录,最终成为经理。
现在,要求用户在被提升时执行此操作似乎是不必要的麻烦。但是对于诸如放置黑锤的问题,这显然是不可接受的。被禁止的用户可能不会友好地及时注销。
有什么方法可以强制将用户添加到角色中,使其立即生效,即使该用户目前已登录?
答案 0 :(得分:0)
我在使用JWT身份验证的Node.js应用程序中经历了类似的情况。在那种情况下,我设置了一个HTTP管道拦截器,如果某些用户声明已更改,它将刷新JWT令牌。
牢记这一点,我发现了this other stack overflow post。看来您做的事情与我上面做的相同。您调整对用户主体的声明,并调用身份验证管理器以重新进行身份验证。您应该能够执行所有操作,而无需用户知道他刚刚注销/登录。
答案 1 :(得分:0)
当用户登录时,声明(包括角色)将保存在cookie或令牌中。这是当时声明 的副本。因此,您正在研究两种不同的来源。 ClaimsIdentity(来自cookie /令牌):
context.User.IsInRole(role)
和数据库:
userManager.AddToRoleAsync(idenityUser, role)
只要cookie或令牌有效,就不会访问该数据库,也不会注意到更改。强制用户再次登录是刷新声明标识的唯一方法。
对于JWT,您可以使用短期令牌,并在访问令牌到期时使用刷新令牌来检索新令牌。这样,声明将在令牌的生存期内自动刷新。对于Cookie,也可能有方法。
但是您在这里面临的主要问题是身份验证与授权混合在一起。这就是问题所在。
该角色不应成为声明标识的一部分,当然也不能在其可以频繁更改的情况下。请注意,应使用(身份)声明对身份(身份验证)进行建模。
解决此问题的最佳方法是将身份验证与授权分开。这样,您可以撤消授权,该授权可以立即生效,而用户无需再次登录。
在这里我将不做详细介绍,因为我是为了自己。但是,如果您有兴趣,请访问我的blog。
答案 2 :(得分:0)
正确的答案是使用UserManager.IsInRoleAsync(identityUser, role)
(docs)而不是ClaimsPrincipal.IsInRole(role)
(在Razor视图中是`User.IsInRole(role)的Context.User.IsInRole(role) )在SignalR集线器中)。
IdentityUser
(docs)从ClaimsPrincipal
获得 UserManager.GetUserAsync(user)
。
因此,完整的代码将是这样的。在剃刀中:
var user = await userManager.GetUserAsync(User);
if (user != null)
if(await userManager.IsInRoleAsync(user))
// ...
在SignalR集线器中:
var user = await userManager.GetUserAsync(Context.User);
if(user != null)
if(await userManager.IsInRoleAsync(user))
// ...
(不确定是否需要空检查,但不会造成伤害)
答案 3 :(得分:-1)
不幸的是,用户将需要注销然后再次登录以刷新其角色,这些角色将被存储为声明。.更新他们的角色之后,您可能只是使他们的登录无效并且这将迫使他们再次登录:< / p>