Owin CookieAuthentication OnValidateIdentity不会调用regenerateIdentityCallback

时间:2016-12-30 14:31:53

标签: c# asp.net-mvc

我正在尝试使用OnValidateIdentity来检查安全标记更改。 但不知怎的,当validateInterval用完时我退出了,验证器没有调用regenerateIdentityCallback这里是来自startup.cs的auth代码

  app.CreatePerOwinContext(() =>
        {
            var uow = DependencyResolver.Current.GetService<IUnitOfWork>();
            return uow.UsersRepository.UserManager;
        });
        app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions()
        {

            Provider = new CookieAuthenticationProvider()
            {
                OnApplyRedirect = context =>
                {
                    if (!context.Request.Path.StartsWithSegments(new PathString("/api")))
                        context.Response.Redirect(context.RedirectUri);
                },
                OnValidateIdentity = context => SecurityStampValidator.OnValidateIdentity<UserManager<User>, User, string>(
                    validateInterval: TimeSpan.FromSeconds(15),
                    regenerateIdentityCallback: (mngr, usr) =>
                    {
                        Debug.WriteLine("Regenerate identity");
                        var rolesStr = (mngr.GetRoles(usr.Id)).ToArray();
                        return AccountController.CreateClaims(usr, rolesStr);
                    },
                    getUserIdCallback: ci => 
                    {
                        return ci.GetUserId();
                    }).Invoke(context)
            },
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/"),
            CookieName = "Alisary",
            ExpireTimeSpan = TimeSpan.FromMinutes(20),
            SlidingExpiration = false,
        });

UserManger位于DAL层。代码:

  public UserRepository(DatabaseContext context, IDataProtectionProvider dataProtection)
    {
        this.context = context;
        this.dataProtectionProvider = dataProtection;
        userManager = new UserManager<User>(
            new UserStore<User>(context));
        userManager.EmailService = new EmailSenderService();
        userManager.UserTokenProvider = new DataProtectorTokenProvider<User>(
            dataProtection.Create("protectionKey"))
        {
            TokenLifespan = TimeSpan.FromHours(24)
        };
        userManager.UserValidator = new UserValidator<User>(userManager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        userManager.PasswordValidator = new PasswordValidator()
        {
            RequiredLength = 6,

        };


        roleManager = new RoleManager<IdentityRole>(
            new RoleStore<IdentityRole>(context));

    }

context是数据库上下文。

2 个答案:

答案 0 :(得分:1)

我设法使用完全自定义的验证提供程序解决了我的问题,而不是使用SecurityStampValidator。

类似于此代码:

 Provider = new CookieAuthenticationProvider()
            {
                OnApplyRedirect = context =>
                {
                    if (!context.Request.Path.StartsWithSegments(new PathString("/api")))
                        context.Response.Redirect(context.RedirectUri);
                },
                OnValidateIdentity = async context =>
                {
                    var uow = DependencyResolver.Current.GetService<IUnitOfWork>();
                    var user = await uow.UsersRepository.FindUserByIdAsync(context.Identity.GetUserId());
                    uow.Reload(user);
                    var oldSecurityStamp = (context.Identity as ClaimsIdentity)
           .Claims.Where(x => x.Type.Equals(ClaimTypes.Expiration))
           .FirstOrDefault().Value;

                    if (!user.SecurityStamp.Equals(oldSecurityStamp))
                    {
                        context.RejectIdentity();
                        context.OwinContext.Authentication.SignOut(context.Options.AuthenticationType);
                    }
                }
                /*SecurityStampValidator.OnValidateIdentity<UserManager<User>, User, string>(
                    validateInterval: TimeSpan.FromSeconds(15),
                    regenerateIdentityCallback: (mngr, usr) =>
                    {
                        Debug.WriteLine("Regenerate identity");
                        var rolesStr = (mngr.GetRoles(usr.Id)).ToArray();
                        return AccountController.CreateClaims(usr, rolesStr);
                    },
                    getUserIdCallback: ci =>
                    {
                        return ci.GetUserId();
                    }).Invoke(context)*/
            },
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/"),
            CookieName = "Alisary",
            ExpireTimeSpan = TimeSpan.FromMinutes(20),
            SlidingExpiration = true,
        });

关于这段代码的唯一问题是,它检查并在每个授权请求中点击数据库,这对我来说很好,因为我知道这不会被正常人击中。

如果有任何解决方案可以使用SecurityStampValidator,我仍然可以提出建议。

感谢。

答案 1 :(得分:1)

您每次通话都在调用一个新的SecurityStampValidator.OnValidateIdentity。为了解决这个问题,请在...之前创建它


var validator = SecurityStampValidator
    .OnValidateIdentity<ApplicationUserManager, ApplicationUser, Guid>(
        validateInterval: TimeSpan.FromSeconds(2),
        regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
        getUserIdCallback: (id) => id.GetUserGuid());

var cookieAuthenticationOptions = new CookieAuthenticationOptions
{
    Provider = new CookieAuthenticationProvider
    {
        // Not called on signin
        OnValidateIdentity = context =>
        {
             return validator.Invoke(context);
        }
    }
};

或者在没有上下文的情况下完成


var cookieAuthenticationOptions = new CookieAuthenticationOptions
{
    Provider = new CookieAuthenticationProvider
    {
        // Not called on signin
        OnValidateIdentity = validator,
    }
};