ASP.NET 身份,立即将其他用户添加到角色(他们不必注销并重新登录)



首先,我知道这个问题: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 => {
            ...
            };
        }

最新更新