Токенът за валидиране на имейл на ASP.NET идентичност винаги е невалиден

Опитвам се да внедря система за покани, при която новосъздадените акаунти получават токен за потвърждение по имейл чрез UserManager.GenerateEmailConfirmationToken и UserManager.ConfirmEmail. Методът ConfirmEmail обаче винаги връща false.

Съгласно предложението в тази публикация, която внедрих моя MachineKeyDataProtector и регистриран в Unity по този начин:

container.RegisterType<IUserTokenProvider<User, Guid>, 
                       DataProtectorTokenProvider<User, Guid>>(new InjectionConstructor(new MachineKeyDataProtector("ASP.NET Identity")));

My UserManager се инжектира с IUserTokenProvider по следния начин:

public UserManager(IUserStore<User, Guid> store, IUserTokenProvider<User, Guid> userTokenProvider)
    : base(store)
{
    // Configure validation logic for passwords
    this.PasswordValidator = new PasswordValidator
    {
        RequiredLength = 6,
        RequireNonLetterOrDigit = false,
        RequireDigit = true,
        RequireLowercase = true,
        RequireUppercase = true,
    };

    this.UserTokenProvider = userTokenProvider;
}

След това капсулирах метода GenerateEmailConfirmationToken в метод на разширение:

public static string GenerateUrlForEmailConfirmationToken(this UserManager<User, Guid> userManager, UrlHelper urlHelper, Guid userId)
{
    var verificationCode = userManager.GenerateEmailConfirmationToken(userId);

    var url = urlHelper.Link(string.Empty, new
    {
        controller = "Account",
        action = "Verify",
        userId = userId,
        verificationCode = verificationCode
    });

    return url;
}

И аз го използвам:

var url = UserManager.GenerateUrlForEmailConfirmationToken(Url, targetUser.Id);
//injects the url in a ready made html template
NotificationService.NotifyNewUser(targetUser, url);

Отстраняване на грешки GenerateUrlForEmailConfirmationToken Видях, че методът за защита на MachineKeyDataProtector се извиква, но премахването на защитата на MachineKeyDataProtector никога не се извиква от ConfirmEmail на UserManager.

Ако променя конфигурацията на DI, за да регистрирам IUserTokenProvider на заявка

container.RegisterType<IUserTokenProvider<User, Guid>, 
                       DataProtectorTokenProvider<User, Guid>>(new PerRequestLifetimeManager(), 
                       new InjectionConstructor(new MachineKeyDataProtector("ASP.NET Identity")));

Тогава премахването на защитата на MachineKeyDataProtector се извиква, но генерира CryptographicException със следното съобщение „Възникна грешка по време на криптографска операция.“.

Възможно ли е това да е причината валидирането винаги да е невярно? Ако е така, как да гарантирам, че методът за премахване на защитата е извикан? Като разглежда обектите и в двете ситуации, UserManager изглежда използва правилния IDataProtector.

Всяка помощ се оценява!


person JCS    schedule 08.02.2015    source източник


Отговори (2)


Имах същия проблем, както споменахте в примерната публикация SO. Използвал съм го както следва. В този случай използвах SimpleInjector IOC, за да регистрирам Usermanager на уеб заявка.

Мисля, че трябва да създадете нов DataProtectorTokenProvider само ако някой от dataProtectionProvider не съществува. Освен това включването на създаване на DataProtectorTokenProvider в конструктора UserManager ще реши проблема.

private static void InitializeUserManager(ApplicationUserManager manager, IAppBuilder app)
        {
            manager.UserValidator = new UserValidator<AspNetApplicationUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };

            // Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = false,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true,
            };

            var dataProtectionProvider = app.GetDataProtectionProvider();

            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider = new DataProtectorTokenProvider<AspNetApplicationUser>(
                  dataProtectionProvider.Create("ASP.NET Identity"))
                {
                    TokenLifespan = TimeSpan.FromHours(3)
                };
            }
        }

Добавих време на живот на токена, но можете да го премахнете, ако не е необходимо.

person DSR    schedule 08.02.2015
comment
Това е правилното. DataProtectionTokenProvider трябва да е сингълтън. Един от ключовете за криптиране е guid, който се генерира при всяко създаване на обекта. - person trailmax; 08.02.2015
comment
Пробата показва, че се използва IDataProtector по подразбиране, това не е предвиденото според stackoverflow.com/questions/23455579/ - person JCS; 08.02.2015

След като се опитах да разбера защо методът SignInManager.PasswordSignIn също винаги се проваля, бе установено, че проблемът е причинен от SecurityStamp не е зададен, когато е трябвало.

Надявам се това да помогне на някой друг.

person JCS    schedule 10.02.2015