为什么 ResetPasswordAsync 不起作用?
Why is ResetPasswordAsync not working?
当我调用下面的代码时,我总是得到 result.Succeeded = false
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var result = await UserManager.ResetPasswordAsync(user.Id, code, model.Password);
//var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
AddErrors(result);
return View();
}
user.Id 和密码的值有效。结果错误总是说 "Invalid Token" 我没有看到它,因为我得到它并立即检查它并出错。这只是一个合理性测试 - 我通常通过电子邮件将令牌发送给用户,但这也不起作用。
更新 1 我在同一个控制器中这样定义 UserManager:
private ApplicationSignInManager _signInManager;
private ApplicationUserManager _userManager;
public AccessController()
{
}
public AccessController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
{
UserManager = userManager;
SignInManager = signInManager;
}
public ApplicationSignInManager SignInManager
{
get
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
}
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
更新 2 这是我的 ApplicationUserManager 代码:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
希望不大,但是如果您的 UserManager
声明它支持用户安全标记,那么请确保在数据库级别用户具有有效的安全标记,更具体地说,它不能具有NULL
邮票。
原因是在生成代码时,如果戳记为 null
,则它会被替换为 string.Empty
,并在生成的重置代码中使用。但是,在验证重置代码时,来自它的标记将直接与来自数据库的标记进行比较,因此您最终可能会将 string.Empty
与 null
进行比较,并因此导致验证失败。
来自 ASP DataProtectorTokenProvider
的 .NET Identity 2.2 源代码(与之前的版本相同):
// GenerateAsync method
if (manager.SupportsUserSecurityStamp)
{
stamp = await manager.GetSecurityStampAsync(user.Id);
}
writer.Write(stamp ?? ""); // Written as "" if null
// ValidateAsync method
if (manager.SupportsUserSecurityStamp)
{
var expectedStamp = await manager.GetSecurityStampAsync(user.Id).WithCurrentCulture();
return stamp == expectedStamp; // Read as "" but compared directly to null
}
当我调用下面的代码时,我总是得到 result.Succeeded = false
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var result = await UserManager.ResetPasswordAsync(user.Id, code, model.Password);
//var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
AddErrors(result);
return View();
}
user.Id 和密码的值有效。结果错误总是说 "Invalid Token" 我没有看到它,因为我得到它并立即检查它并出错。这只是一个合理性测试 - 我通常通过电子邮件将令牌发送给用户,但这也不起作用。
更新 1 我在同一个控制器中这样定义 UserManager:
private ApplicationSignInManager _signInManager;
private ApplicationUserManager _userManager;
public AccessController()
{
}
public AccessController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
{
UserManager = userManager;
SignInManager = signInManager;
}
public ApplicationSignInManager SignInManager
{
get
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
}
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
更新 2 这是我的 ApplicationUserManager 代码:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
希望不大,但是如果您的 UserManager
声明它支持用户安全标记,那么请确保在数据库级别用户具有有效的安全标记,更具体地说,它不能具有NULL
邮票。
原因是在生成代码时,如果戳记为 null
,则它会被替换为 string.Empty
,并在生成的重置代码中使用。但是,在验证重置代码时,来自它的标记将直接与来自数据库的标记进行比较,因此您最终可能会将 string.Empty
与 null
进行比较,并因此导致验证失败。
来自 ASP DataProtectorTokenProvider
的 .NET Identity 2.2 源代码(与之前的版本相同):
// GenerateAsync method
if (manager.SupportsUserSecurityStamp)
{
stamp = await manager.GetSecurityStampAsync(user.Id);
}
writer.Write(stamp ?? ""); // Written as "" if null
// ValidateAsync method
if (manager.SupportsUserSecurityStamp)
{
var expectedStamp = await manager.GetSecurityStampAsync(user.Id).WithCurrentCulture();
return stamp == expectedStamp; // Read as "" but compared directly to null
}