Ole*_* Sh 49 c# reset-password asp.net-mvc-5 asp.net-identity-2
我需要能够通过管理员更改用户的密码.因此,管理员不应输入用户的当前密码,他应该有能力设置新密码.我查看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);
}
Run Code Online (Sandbox Code Playgroud)
它有效,但理论上我们可以在AddPasswordAsync方法上收到错误.因此,旧密码将被删除,但未设置新密码.这不好.有什么方法可以在"一次交易"中做到吗?PS.我看到ResetPasswordAsync方法带有重置令牌,似乎,它更安全(因为不能与用户不稳定的情况)但无论如何,它通过2个动作.
bry*_*n c 52
这个方法对我有用:
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();
}
Run Code Online (Sandbox Code Playgroud)
Lee*_*unn 46
编辑:我知道OP请求一个在一个事务中执行任务的答案,但我认为代码对人们有用.
所有答案都直接使用PasswordHasher,这不是一个好主意,因为你将失去一些功能(验证等).
另一种选择(我会假设建议的方法)是创建密码重置令牌,然后使用它来更改密码.例:
var user = await UserManager.FindByIdAsync(id);
var token = await UserManager.GeneratePasswordResetTokenAsync(user);
var result = await UserManager.ResetPasswordAsync(user, token, "MyN3wP@ssw0rd");
Run Code Online (Sandbox Code Playgroud)
Tse*_*eng 33
ApplicationUserManager
是ASP.NET模板生成的类.
这意味着,您可以编辑它并添加它尚未拥有的任何功能.UserManager类有一个名为protected的属性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);
}
}
Run Code Online (Sandbox Code Playgroud)
该UserManager
不是别的,只是一个包装底层UserStore
.检查出IUserPasswordStore
的接口文档MSDN上可用的方法.
编辑:
这PasswordHasher
也是UserManager
该类的公共属性,请参阅此处的接口定义.
编辑2:
由于有些人天真地相信,你不能用这种方式进行密码验证,我已经更新了.该PasswordValidator
属性也是一个属性,UserManager
它就像添加2行代码一样简单,以添加密码验证(虽然这不是原始问题的要求).
小智 13
我认为解决方案更容易
public async Task<IdentityResult> ResetPasswordAsync(ApplicationUser user, string password)
{
string token = await userManager.GeneratePasswordResetTokenAsync(user);
return await userManager.ResetPasswordAsync(user, token, password);
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*vid 10
在 .net 核心 3.0 中
var token = await UserManager.GeneratePasswordResetTokenAsync(user);
var result = await UserManager.ResetPasswordAsync(user, token, password);
Run Code Online (Sandbox Code Playgroud)
这只是对@Tseng提供的答案的改进.(我不得不调整它以使其工作).
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;
}
}
Run Code Online (Sandbox Code Playgroud)
注意:这特别适用于int
用作用户和角色主键的已修改设置.我相信这只是删除<AppUser, int>
类型args以使其与默认的ASP.NET标识设置一起使用的问题.