首先,我知道这个问题:MVC 5 AddToRole 需要注销才能工作?
还有这个:ASP.NET Identity的IUserSecurityStampStore
因此,请不要将其标记为重复项。
我正在尝试将另一个用户添加到角色(即我们要添加到角色的用户不是当前用户。如果是,我链接到的第一个问题的答案就足够了。
这样:
IdentityResult result = await userManager.AddToRoleAsync(userID, roleName);
我这样做的两种情况是:从管理页面,当前用户是管理员;以及使用基本身份验证保护的 Webhook(根本没有当前用户)。
问题:如果应用此更改的用户已登录并使用该应用程序,则需要立即应用"添加到角色"更改。他们不必注销并再次登录即可进行更改,并且需要立即发生。
谢谢大家。
编辑:顺便说一下,User.IsInRole(roleName) 需要注销和登录才能反映被添加到新角色。UserManager.IsInRole(userID, roleName) 没有,因为(我假设)它直接进入数据库表进行检查。但是,如果用户点击了使用他们刚刚添加到的角色保护的操作方法,他们仍然必须再次登录,这很公平。仍然很好奇是否有办法解决这个问题。
编辑:以下是"授权"属性的源代码:https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/src/System.Web.Mvc/AuthorizeAttribute.cs
它使用User.IsInRole,这基本上是我们需要再次登录的原因。似乎覆盖的方法是AuthorizeCore(HttpContextBase httpContext)。我现在没有勇气或足够好来搞砸这个,但如果你想试一试,很多人会发现这很有帮助。
从问题的底部开始。 User.IsInRole()
进入用户 Cookie 并检查该 Cookie 中存储了哪些角色。因此,它需要重新登录才能使更改生效。是的,您说UserManager.IsInRole()
检查数据库而不是cookie是正确的。
若要确保立即应用角色更改,需要检查每个请求中的角色更改。要做到这一点,Startup.Auth.cs
找到以下行:
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(0), // <-- This is zero. Check on every request
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
这是框架更新 cookie 的方式。默认情况下,validateInterval
设置为 30 分钟。如果将其设置为零,系统将为每个请求创建一个新的 cookie,其中包含更新的角色。如果您有足够多的用户同时访问您的系统,则数据库负载可能太大。所以我将时间跨度增加到 30 秒-1-2 分钟。
此功能旨在通过单个密码更改注销所有会话。但也非常适合您的目的。
在 ASP.NET Core中,SignInManager.RefreshSignInAsync() 解决了这个问题。
对于 ASP.NET 核心身份 2,解决方案是使用:
services.Configure<SecurityStampValidatorOptions>(options =>
{
options.ValidationInterval = TimeSpan.FromMinutes(1);
});
每分钟强制更新一次,或使用 TimeSpan.Zero 在用户每次访问页面时强制更新(请注意,每次执行数据库请求时)。
还要确保,如果覆盖 cookie 事件,请不要使用:
services.ConfigureApplicationCookie(options =>
{
options.Events = new CookieAuthenticationEvents(){
...
};
}
但直接覆盖您需要的事件,否则不会调用验证:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = ctx => {
...
};
}