Изменение пароля

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 15.12.2019

В прошлой теме было рассмотрено редактирование пользователя. Однако процесс редактирования не включал изменение пароля. В этой же теме рассмотрим, как отдельно сменить пароль пользователя.

Вначале создадим модель представления ChangePasswordViewModel:

public class ChangePasswordViewModel
{
    public string Id { get; set; }
    public string Email { get; set; }
    public string NewPassword { get; set; }
}

Здесь определены свойства для Id и электронной почты пользователя, а также для нового пароля.

Далее добавим в контроллер UsersController, который был создан в прошлой теме, новое действие ChangePassword:

public async Task<IActionResult> ChangePassword(string id)
{
    User user = await _userManager.FindByIdAsync(id);
    if (user == null)
    {
        return NotFound();
    }
    ChangePasswordViewModel model = new ChangePasswordViewModel { Id = user.Id, Email = user.Email};
    return View(model);
}

[HttpPost]
public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        User user = await _userManager.FindByIdAsync(model.Id);
        if (user != null)
		{
			var _passwordValidator = 
				HttpContext.RequestServices.GetService(typeof(IPasswordValidator<User>)) as IPasswordValidator<User>;
			var _passwordHasher =
				HttpContext.RequestServices.GetService(typeof(IPasswordHasher<User>)) as IPasswordHasher<User>;
    
            IdentityResult result = 
                await _passwordValidator.ValidateAsync(_userManager, user, model.NewPassword);
            if(result.Succeeded)
            {
                user.PasswordHash = _passwordHasher.HashPassword(user, model.NewPassword);
                await _userManager.UpdateAsync(user);
                return RedirectToAction("Index");
            }
            else
            {
                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Пользователь не найден");
        }
    }
    return View(model);
}

Таблица пользователей не хранит оригинальный пароль, а вместо него хранит хеш пароля. Для его получения мы можем воспользоваться методом HashPassword() сервиса IPasswordHasher, который добавляется вместе со всеми сервисами ASP.NET Core Identity через механизм внедрения зависимостей.

Однако перед созданием хеша нам надо валидировать пароль с помощью валидатора. Валидатор пароля также можно получить из коллекции сервисов приложения в виде объекта IPasswordValidator.

Затем добавим представление ChangePassword.cshtml:

@model CustomIdentityApp.ViewModels.ChangePasswordViewModel
@{
    ViewBag.Title = "Изменение пароля";
}
<h2>Изменение пароля для пользователя @Model.Email</h2>
<form asp-action="ChangePassword" asp-controller="Users">
    <div asp-validation-summary="All" class="text-danger"></div>

    <input type="hidden" asp-for="Id" />
    <input type="hidden" asp-for="Email" />
	
    <div class="form-group">
        <label asp-for="NewPassword" class="control-label">Новый пароль</label>
        <input type="text" asp-for="NewPassword" class="form-control" />
    </div>
    <div class="form-group">
        <input type="submit" value="Сохранить" class="btn btn-outline-dark" />
    </div>
</form>

И в конце добавим на представление Index.cshtml ссылку для смены пароля:

@model IEnumerable<CustomIdentityApp.Models.User>
@{
    ViewBag.Title = "Список пользователей";
}

<a asp-action="Create">Добавить пользователя</a>

<table class="table">
    <tr><th>Email</th><th>Год</th><th></th></tr>
    @foreach (var user in Model)
    {
        <tr>
            <td>@user.Email</td>
            <td>@user.Year</td>
            <td>
                <form asp-action="Delete" asp-route-id="@user.Id" method="post">
                    <a class="btn btn-sm btn-primary" asp-action="Edit" asp-route-id="@user.Id">Изменить</a>
                    <a class="btn btn-sm btn-primary" asp-action="ChangePassword" asp-route-id="@user.Id">Сменить пароль</a>
                    <button type="submit" class="btn btn-sm btn-danger">
                        Удалить
                    </button>
                </form>
            </td>
        </tr>
    }
</table>
Смена пароля в ASP.NET Core Identity

Второй вариант

В предыдущем случае мы явным образом создавали хеш пароля и обновляли пользователя. Однако мы можем воспользоваться и другим методом - методом ChangePasswordAsync() класса UserManager. Он в качестве параметра принимает объект пользователя, старый и новый пароль. То есть, чтобы сменить пароль на новый, нам надо указать также и старый, что может быть целесообразно в различных ситуациях.

Для этого изменим модель ChangePasswordViewModel:

public class ChangePasswordViewModel
{
    public string Id { get; set; }
    public string Email { get; set; }
    public string NewPassword { get; set; }
    public string OldPassword { get; set; }
}

Изменим post-версию метода ChangePassword:

[HttpPost]
public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        User user = await _userManager.FindByIdAsync(model.Id);
        if (user != null)
        {
            IdentityResult result = 
                await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
            if(result.Succeeded)
            {
                return RedirectToAction("Index");
            }
            else
            {
                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Пользователь не найден");
        }
    }
    return View(model);
}

И соответственно изменим представление ChangePassword.cshtml:

@model CustomIdentityApp.ViewModels.ChangePasswordViewModel
@{
    ViewBag.Title = "Изменение пароля";
}
<h2>Изменение пароля для пользователя @Model.Email</h2>
<form asp-action="ChangePassword" asp-controller="Users">
    <div asp-validation-summary="All" class="text-danger"></div>

    <input type="hidden" asp-for="Id" />
    <input type="hidden" asp-for="Email" />
	<div class="form-group">
        <label asp-for="OldPassword" class="control-label">Старый пароль</label>
        <input type="text" asp-for="OldPassword" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="NewPassword" class="control-label">Новый пароль</label>
        <input type="text" asp-for="NewPassword" class="form-control" />
    </div>
    <div class="form-group">
        <input type="submit" value="Сохранить" class="btn btn-default" />
    </div>
</form>
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850