【问题标题】:ASP Identity 2.0: Regenerate IdentityASP Identity 2.0:重新生成身份
【发布时间】:2014-12-21 19:03:00
【问题描述】:

我无法让 ASP 标识按需刷新其存储在 cookie 中的标识。

Startup.Auth.cs 文件中,cookie 设置为重新生成,如下所示:

app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<QuizSparkUserManager, QuizSparkUser, int>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentityCallback: ((manager, user) => manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)),
                    getUserIdCallback: ((claimsIdentity) => int.Parse(claimsIdentity.GetUserId())))
                }
            });

但是我不知道如何在代码中刷新 User.Identity 上的内容,即在我需要刷新身份 cookie 时强制刷新它。

我希望能够以编程方式使用重新生成身份回调,这可能吗?

我的问题和这个类似:How to invalidate .AspNet.ApplicationCookie after Adding user to Role using Asp.Net Identity 2?

但是我想刷新而不是使 cookie 无效。

编辑


查看链接的问题后,我尝试了以下操作(没有完整的错误处理):

IOwinContext context = Request.GetOwinContext();
QuizSparkSignInManager manager = context.Get<QuizSparkSignInManager>();
ClaimsIdentity newIdentity = manager.CreateUserIdentity(manager.UserManager.FindById(User.Identity.GetUserId<int>()));

AuthenticateResult authenticationContext =
                    await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie);

if (authenticationContext != null)
{
    context.Authentication.AuthenticationResponseGrant = new AuthenticationResponseGrant(
                        newIdentity, authenticationContext.Properties);
}

bool first2 = User.IsInRole("Turtle");

Edit2:但是用户似乎仍然没有刷新。在页面重新加载时,它们似乎确实刷新了,我是否认为这是因为 User.Identity cookie 是请求的一部分并且不能在代码中更改?

【问题讨论】:

  • 你想通过刷新 cookie 做什么?
  • 正如您在回答中提到的那样,当用户被添加到角色时,我正在尝试刷新用户角色。
  • 这是一个非常相似的问题:stackoverflow.com/a/19354940/809357

标签: c# asp.net cookies asp.net-identity-2


【解决方案1】:

如果您尝试向已登录的用户添加新角色,则需要将用户注销。然后使用新角色创建新身份并使用新身份登录用户。这是更新 cookie 的唯一方法。

检查用户属性是否已更改的最佳位置是在您已经使用的回调中:CookieAuthenticationProvider.OnValidateIdentity。像这样。

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    // other stuff
    Provider = new CookieAuthenticationProvider
    {
        // this function is executed every http request and executed very early in the pipeline
        // and here you have access to cookie properties and other low-level stuff. 
        // makes sense to have the invalidation here
        OnValidateIdentity = async context =>
        {
            // invalidate user cookie if user's security stamp have changed
            var invalidateBySecirityStamp = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager));
            await invalidateBySecirityStamp.Invoke(context);

            if (context.Identity == null || !context.Identity.IsAuthenticated)
            {
                return;
            }
            if(/*Need to update cookie*/)
            {
                // get user manager. It must be registered with OWIN
                var userManager = context.OwinContext.GetUserManager<UserManager>();
                var username = context.Identity.Name;

                // get new user identity with updated properties
                var updatedUser = await userManager.FindByNameAsync(username);

                // updated identity from the new data in the user object
                var newIdentity = updatedUser.GenerateUserIdentityAsync(manager);

                // kill old cookie
                context.OwinContext.Authentication.SignOut(context.Options.AuthenticationType);

                // sign in again
                var authenticationProperties = new AuthenticationProperties() { IsPersistent = context.Properties.IsPersistent };
                context.OwinContext.Authentication.SignIn(authenticationProperties, newIdentity);
            }
        }
    }
});  

免责声明 - 从未测试过,甚至没有尝试编译它。

也可以see my other answer 参考 - 几乎相同的代码,但不同的目标。

统一更新: 关于问题的另一部分 - 如何检测角色变化:
我可以想到一种方法 - 在用户记录上设置另一个 GUID。类似于SecurityStamp,但不被框架使用。叫它MySecurityStamp。在登录时将值 MySecurityStamp 添加到 cookie 作为声明。在每个请求上,将 cookie 中的 MySecurityStamp 值与数据库中的值进行比较。如果值不同 - 是时候重新生成身份了。并在每个添加/删除的新角色上为数据库中的用户修改 MySecurityStamp。这将涵盖所有浏览器中的所有会话。

【讨论】:

  • 目前我只重新生成身份并登录,您是否碰巧知道是否需要额外的注销才能杀死cookie,或者它是否会因调用Authentication.AuthenticationResponseGrant而失效?
  • 你为什么使用Authentication.AuthenticationResponseGrant?我认为这不应该被 OWIN 本身以外的任何东西所消耗。要杀死 cookie,您需要使用 Authentication.AuthenticationResponseRevoke(或类似的东西,不确定命名)。无论如何,只需使用SignOut - 在后台为您进行响应和授权。
  • @FelipeCorrea 一种方法是在用户NeedUpdating 上放置一个布尔标志,而不是/*Need to update cookie*/ 检查用户对象上的标志。重新登录后,将此标志设置为false。如果用户打开了多个会话,则此方法会出现问题 - 它只会在一个浏览器中更新 cookie。
  • @trailmax 感谢您的回答!不过那是个大问题……我想如果我注销用户并从代码中再次给他签名,也会存在同样的问题,对吧?有什么办法可以覆盖所有浏览器会话?我真的很担心像 manager.RegenerateCookieAsync() 这样的管理器本身没有原生地实现像这样的简单需求。请,如果您能对另一种方法提出任何建议,我们将不胜感激!
  • @FelipeCorrea 您不必针对每个请求访问数据库 - 您可以将其设置为每隔几分钟左右 - 取决于您希望更改以多快的速度反映在用户身上。并且每次重新创建 cookie 比一次 DB 命中更昂贵。我做了一次计时,由于发生了加密,重新创建 cookie 是一项相当大的工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 2019-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-08
  • 1970-01-01
相关资源
最近更新 更多