我有一个使用ASP.NET核心授权的SQLite数据连接的ASP.NET核心MVC站点,如下所示:
// Startup.ConfigureServices
services.AddAuthorization(e =>
{
e.AddPolicy(Policies.UserRead, b => b.RequireRole("Editor", "Root"));
}
这是限制使用用户信息访问网站的政策之一。 (Policies.UserRead
是常量string
)。然后将此策略应用于此视图:
[Authorize(Policies.UserRead)]
public async Task<IActionResult> Index()
{
}
效果很好,只有角色为Editor
或Root
的用户才能访问该视图。但是当登录时改变用户的角色时会出现问题。例如
Editor
)登录并使用Index()
- 成功 Root
)登录并从用户A中删除角色Editor
Index()
- 仍然成功 您可能希望用户A不再访问Index()
,因为他不再是Editor
角色。 Buuuut他仍然可以 - 只要他不退出并重新登录,因为重新解决修复了这个问题。似乎有人(我认为ClaimsPrincipal
是罪魁祸首)缓存了角色 - 如果我知道如何使缓存失效,那将是OK
...
角色转换代码:
// get the user whos role is changed
var targetUser = await _context.Users.SingleOrDefaultAsync(m => m.Id == model.Id);
if (targetUser == null) return NotFound();
// get the user who changes the role
var sourceUser = await _userManager.GetUserAsync(User);
if (sourceUser == null) return RedirectToAction("Index");
// remove the current role
await _userManager.RemoveFromRoleAsync(targetUser, targetUser.Role.ToString());
// add to the new role
await _userManager.AddToRoleAsync(targetUser, model.Role.ToString());
// update & save the changes
_context.Update(targetUser);
await _context.SaveChangesAsync();
这基本上是我用来改变用户角色的代码(我剪掉了视图/模型部分因为它们无关紧要)。注意:
targetUser
和sourceUser
都是ApplicationUser
(实现IdentityUser
)。
_userManger
- 谁会想到 - 类型UserManager<ApplicationManger>
我尝试使用SignInManger<>
重新启动用户,但似乎您只能注销当前用户 - 即更改角色的用户,而不是更改角色的用户。
我错过了什么?如果用户不必做任何事情(例如重新登录)以便&#34;刷新&#34; 用户角色,那就太好了。
答案 0 :(得分:1)
问题是用户的角色声明存储在cookie中(aspnet身份的默认实现),因此即使用户的角色发生变化,除非用户退出,否则授权结果不会改变。解决方案是使用ValidateAsync
事件。 Example存在于官方文档中。
另一种可能的解决方案是从cookie中排除角色声明并使用声明转换。
为此,您需要覆盖CreateAsync
的{{1}}方法,请参阅此article如何更改声明。然后,您可以使用claims transformation添加角色声明。