我需要能够通过管理员更改用户的密码。因此,管理员不应输入用户的当前密码,他应该有能力设置新密码。我查看ChangePasswordAsync方法,但此方法需要输入旧密码。因此,此方法不适合此任务。因此我通过以下方式做到了:
[HttpPost]
public async Task<ActionResult> ChangePassword(ViewModels.Admin.ChangePasswordViewModel model)
{
var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
var result = await userManager.RemovePasswordAsync(model.UserId);
if (result.Succeeded)
{
result = await userManager.AddPasswordAsync(model.UserId, model.Password);
if (result.Succeeded)
{
return RedirectToAction("UserList");
}
else
{
ModelState.AddModelError("", result.Errors.FirstOrDefault());
}
}
else
{
ModelState.AddModelError("", result.Errors.FirstOrDefault());
}
return View(model);
}
它可以工作,但理论上我们可以在AddPasswordAsync方法上收到错误。因此,旧密码将被删除,但未设置新密码。这不好。任何方式在&#34;一个交易&#34;? PS。我看到ResetPasswordAsync方法带有重置令牌,似乎更安全(因为用户不能处于不稳定状态),但无论如何,它通过2个动作完成。
答案 0 :(得分:46)
这种方法对我有用:
public async Task<IHttpActionResult> changePassword(UsercredentialsModel usermodel)
{
ApplicationUser user = await AppUserManager.FindByIdAsync(usermodel.Id);
if (user == null)
{
return NotFound();
}
user.PasswordHash = AppUserManager.PasswordHasher.HashPassword(usermodel.Password);
var result = await AppUserManager.UpdateAsync(user);
if (!result.Succeeded)
{
//throw exception......
}
return Ok();
}
答案 1 :(得分:36)
所有答案都直接使用PasswordHasher,这不是一个好主意,因为你将失去一些功能(验证等)。
另一种选择(我会假设推荐的方法)是创建密码重置令牌,然后使用它来更改密码。例如:
var user = await UserManager.FindByIdAsync(id);
var token = await UserManager.GeneratePasswordResetTokenAsync(user);
var result = await UserManager.ResetPasswordAsync(user, token, "MyN3wP@ssw0rd");
答案 2 :(得分:27)
ApplicationUserManager
是ASP.NET模板生成的类。
这意味着,您可以编辑它并添加它尚未拥有的任何功能。 UserManager类有一个名为Store
的受保护属性,它存储对UserStore
类(或其任何子类)的引用,具体取决于您配置ASP.NET标识的方式或是否使用自定义用户存储实现,即如果您使用不同的数据库引擎,如MySQL)。
public class AplicationUserManager : UserManager<....>
{
public async Task<IdentityResult> ChangePasswordAsync(TKey userId, string newPassword)
{
var store = this.Store as IUserPasswordStore;
if(store==null)
{
var errors = new string[]
{
"Current UserStore doesn't implement IUserPasswordStore"
};
return Task.FromResult<IdentityResult>(new IdentityResult(errors) { Succeeded = false });
}
if(PasswordValidator != null)
{
var passwordResult = await PasswordValidator.ValidateAsync(password);
if(!password.Result.Success)
return passwordResult;
}
var newPasswordHash = this.PasswordHasher.HashPassword(newPassword);
await store.SetPasswordHashAsync(userId, newPasswordHash);
return Task.FromResult<IdentityResult>(IdentityResult.Success);
}
}
UserManager
只不过是底层UserStore
的包装器。查看MSDN关于可用方法的IUserPasswordStore
界面文档。
修改强>
PasswordHasher
也是UserManager
类的公共属性,请参阅interface definition here。
编辑2:
由于有些人天真地相信,你不能用这种方式进行密码验证,我已经更新了。 PasswordHasher
属性也是UserManager
的属性,就像添加2行代码以添加密码验证一样简单(虽然这不是原始问题的要求)。
答案 3 :(得分:7)
在.net core 3.0中
var token = await UserManager.GeneratePasswordResetTokenAsync(user);
var result = await UserManager.ResetPasswordAsync(user, token, password);
答案 4 :(得分:5)
这只是对@Tseng提供的答案的改进。 (我不得不调整它以使其工作)。
id
注意:这特别适用于使用public class AppUserManager : UserManager<AppUser, int>
{
.
// standard methods...
.
public async Task<IdentityResult> ChangePasswordAsync(AppUser user, string newPassword)
{
if (user == null)
throw new ArgumentNullException(nameof(user));
var store = this.Store as IUserPasswordStore<AppUser, int>;
if (store == null)
{
var errors = new string[] { "Current UserStore doesn't implement IUserPasswordStore" };
return IdentityResult.Failed(errors);
}
var newPasswordHash = this.PasswordHasher.HashPassword(newPassword);
await store.SetPasswordHashAsync(user, newPasswordHash);
await store.UpdateAsync(user);
return IdentityResult.Success;
}
}
作为用户和角色主键的修改后的设置。我相信这只是删除int
类型args以使其与默认的ASP.NET标识设置一起使用的问题。
答案 5 :(得分:2)
public async Task<IActionResult> ChangePassword(ChangePwdViewModel usermodel)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = await _userManager.FindByIdAsync(userId);
var result = await _userManager.ChangePasswordAsync(user, usermodel.oldPassword, usermodel.newPassword);
if (!result.Succeeded)
{
//throw exception......
}
return Ok();
}
public class ChangePwdViewModel
{
[DataType(DataType.Password), Required(ErrorMessage ="Old Password Required")]
public string oldPassword { get; set; }
[DataType(DataType.Password), Required(ErrorMessage ="New Password Required")]
public string newPassword { get; set; }
}
注意:此处我正在从当前登录用户中检索UserId。
答案 6 :(得分:1)
如果您没有用户的当前密码,但仍想更改密码。相反,您可以做的是先删除用户的密码,然后添加新密码。这样,您将能够更改用户密码而无需该用户的当前密码。
await UserManager.RemovePasswordAsync(user);
await UserManager.AddPasswordAsync(user, model.Password);
答案 7 :(得分:1)
对于ASP.NET Core 3.1
用户,这是@Tseng和@BCA提供的出色答案的现代化迭代。
PasswordValidator
不再是UserManager
的属性-而是该属性为IList PasswordValidators
。此外,Identity现在具有protected UpdatePasswordHash
方法,无需直接访问UserStore
即可为您更改密码,从而无需手动散列并保存密码。
UserManager
还有一个公共属性bool SupportsUserPassword
,它代替了测试Store
是否实现IUserPasswordStore
的需要(内部,这正是UserManager
在SupportsUserPassword
吸气剂中进行)。
由于UpdatePasswordHash
是protected
,因此您仍然需要扩展基础UserManager
。它的签名是:
protected Task<IdentityResult> UpdatePasswordHash(TUser user, string newPassword, bool validatePassword)
其中validatePassword
代表是否运行密码验证。不幸的是,不是默认为true
,因此需要提供它。实现看起来像这样:
public async Task<IdentityResult> ChangePasswordAsync(ApplicationUser user, string newPassword)
{
if (!SupportsUserPassword)
{
return IdentityResult.Failed(new IdentityError
{
Description = "Current UserStore doesn't implement IUserPasswordStore"
});
}
var result = await UpdatePasswordHash(user, newPassword, true);
if (result.Succeeded)
await UpdateAsync(user);
return result;
}
像以前一样,首先要确保当前的UserStore
支持密码。
然后,只需使用UpdatePasswordHash
,新密码和ApplicationUser
调用true
,即可通过验证更新该用户的密码。如果更新成功,则仍然必须保存用户,因此请致电UpdateAsync
。
答案 8 :(得分:1)
我认为解决方案要容易得多
public async Task<IdentityResult> ResetPasswordAsync(ApplicationUser user, string password) {
string token = await userManager.GeneratePasswordResetTokenAsync(user);
return await userManager.ResetPasswordAsync(user, token, password);
}
答案 9 :(得分:0)
public async Task<ActionResult> ChangePassword(ResetPasswordViewModel CP)
{
ApplicationDbContext context = new ApplicationDbContext();
UserStore<ApplicationUser> store = new UserStore<ApplicationUser>(context);
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(store);
var user = await UserManager.FindAsync(User.Identity.Name, CP.CurrentPassword);
if (!UserManager.CheckPassword(user, CP.CurrentPassword))
{
ViewBag.notification = "Incorrect password.";
return View("~/Views/User/settings.cshtml");
}
else
{
if (CP.Password != CP.ConfirmPassword)
{
ViewBag.notification = "try again";
return View("~/Views/User/settings.cshtml");
}
else
{
String hashedNewPassword = UserManager.PasswordHasher.HashPassword(CP.Password);
await store.SetPasswordHashAsync(user, hashedNewPassword);
await store.UpdateAsync(user);
ViewBag.notification = "successful";
return View("~/Views/User/settings.cshtml");
}
}
}
答案 10 :(得分:-1)
ListAPIView
答案 11 :(得分:-2)