[ Полезный рекламный блок ]
Попробуйте свои силы в игре, где ваши навыки программирования на C# станут решающим фактором. Переходите по ссылке 🔰.
Одной из распространенных практик управления учетными записями пользователей является предоставление пользователям возможности изменить свой пароль, если они его забыли.
Процесс сброса пароля не должен вовлекать администраторов приложений, поскольку пользователи сами должны быть в состоянии пройти через весь процесс самостоятельно. Обычно на странице входа в систему пользователю предоставляется ссылка «Забыли пароль«, и в данной статье речь пойдет именно об этом.
Итак, давайте рассмотрим, как должен работать процесс сброса пароля.
Пользователь нажимает на ссылку «Забыли пароль» и попадает в представление с полем электронной почты. После того как пользователь заполняет это поле, приложение отправляет действительную ссылку на этот email. Владелец электронной почты нажимает на ссылку и перенаправляется на представление сброса пароля со сгенерированным токеном. После заполнения всех полей формы приложение сбрасывает пароль, и пользователь перенаправляется на страницу входа (или главную).
Восстановление пароля в Asp.Net Core Identity
- Восстановление пароля
- Определение классов и действий для генерации и отправки ссылки
- Определение действий для сброса пароля
Чтобы писать вместе со мной, вам придется установить .NET Core 2.2, а также Visual Studio 2017-2022. Вы также можете использовать другую IDE вместо Visual Studio.
ВАЖНО! Создание проекта, добавление Identity, разработка страницы авторизации и регистрации не рассматривается в этой статье. Добавление Identity в проект с нуля, добавление возможности авторизации, регистрации и ролей, вы можете рассмотреть на этом прекрасно сайте — Metanit. Мы же сконцентрируемся только на теме «Восстановления пароля в ASP.NET Core Identity».
Восстановление пароля
Пользователь имеет возможность сбросить пароль учетной записи. Для этого ему на почту мы будем отправлять ссылку с токеном внутри, перейдя по которой, пользователь сможет ввести новый пароль учетной записи.
Сначала добавим метод расширения AddDefaultTokenProviders, в класс Program.cs, чтобы включить генерацию токенов в приложении, для этого добавим вызов метода к AddIdentity:
1 2 3 4 |
//Удаляем //builder.Services.AddIdentity<User, IdentityRole>().AddEntityFrameworkStores<ApplicationContext>(); builder.Services.AddIdentity<User, IdentityRole>().AddEntityFrameworkStores<ApplicationContext>().AddDefaultTokenProviders(); |
Identity создаст токен после отправки письма со сбросом пароля. Этот токен будет использоваться для соответствия запросу, приходящему в Identity, когда пользователь нажимает на письмо со сброшенным паролем. Identity убедится, что токен действителен и не просрочен, прежде чем разрешить пользователю сбросить пароль. Отличная функция, не правда ли?
Мы также можем установить время действия токена, добавив приведенный ниже код в класс Program.cs:
1 2 |
//Время действия токена - 10 часов builder.Services.Configure<DataProtectionTokenProviderOptions>(opts => opts.TokenLifespan = TimeSpan.FromHours(10)); |
Здесь мы установили срок действия токена в 10 часов. Это означает, что пользователь может изменить в течение 10 часов.
Определение классов и действий для генерации и отправки ссылки
Начнем с добавления нового метода действия ForgotPassword в контроллере AccountController. Работа действия будет заключаться в отправке электронного письма на почтовый ящик пользователя со ссылкой для сброса пароля.
Мы также добавили еще одно действие под названием ForgotPasswordConfirmation, работа которого заключается в показе подтверждающего сообщения, говорящего пользователю, что письмо со сбросом пароля отправлено успешно, и теперь ему нужно проверить свой почтовый ящик на наличие письма.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
[AllowAnonymous] [HttpGet] public IActionResult ForgotPassword() { return View(); } [AllowAnonymous] [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> ForgotPassword([Required] string email) { if (!ModelState.IsValid) return View(model:email); var user = await _userManager.FindByEmailAsync(email); if (user == null) return RedirectToAction(nameof(ForgotPasswordConfirmation)); var token = await _userManager.GeneratePasswordResetTokenAsync(user); var link = Url.Action("ResetPassword", "Account", new { token, email = user.Email }, Request.Scheme); EmailHelper emailHelper = new EmailHelper(); bool emailResponse = emailHelper.SendEmailPasswordReset(user.Email, link); if (emailResponse) return RedirectToAction(nameof(ForgotPasswordConfirmation)); else { // log email failed ModelState.AddModelError("","Произошла ошибка, попробуйте позже."); } return View(model:email); } [AllowAnonymous] [HttpGet] public IActionResult ForgotPasswordConfirmation() { return View(); } |
Мы создали токен сброса пароля с помощью метода GeneratePasswordResetTokenAsync класса UserManager<T>. Затем мы добавили этот токен к ссылке. Эта ссылка будет использоваться как ссылка сброса пароля.
Теперь установим зависимости, если они еще не установлены в вашей IDE:
- MailKit
- MimeKit
Можно также выполнить установку через Package Manager Console:
1 |
Install-Package MailKit |
Затем мы вызвали метод SendEmailPasswordReset() класса EmailHelper, чтобы отправить письмо пользователю.
Добавим в проект папку Helpers и в ней определим класс EmailHelper, со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public class EmailHelper { public bool SendEmailPasswordReset(string userEmail, string link) { var message = new MimeMessage(); //от кого отправляем и заголовок message.From.Add(new MailboxAddress("WebApplication1 Project", "enykoruna1@gmail.com")); //кому отправляем message.To.Add(new MailboxAddress("Имя Человека", userEmail)); //тема письма message.Subject = "Сброс пароля на сайте WebApplication1"; //тело письма message.Body = new TextPart("html") { Text = link, }; using (var client = new SmtpClient()) { //Указываем smtp сервер почты и порт client.Connect("smtp.gmail.com", 587, false); //Указываем свой Email адрес и пароль приложения client.Authenticate("mail@gmail.com", "password"); try { client.Send(message); return true; } catch (Exception) { //Logging information } finally { client.Disconnect(true); } } return false; } } |
Как выполнять отправку письма, получать пароли приложений, детально рассматривается в статье «Отправка Email в Asp.Net Core«.
Теперь определим представления для сброса пароля, в папке Views – Account.
Добавим представление ForgotPassword.cshtml, со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@model string @{ ViewData["Title"] = "Сброс пароля"; } <h1 class="bg-info text-white">Сброс пароля</h1> <form asp-action="ForgotPassword" method="post"> <div class="form-group"> <label>Email</label> <input name="email" class="form-control" /> </div> @Html.AntiForgeryToken() <button class="btn btn-primary" type="submit">Подтвердить</button> </form> |
Так же, добавим представление ForgotPasswordConfirmation.cshtml, со следующим содержимым:
1 2 3 4 5 6 7 8 |
@{ ViewData["Title"] = "Подтверждение пароля"; } <h1>Подтверждение пароля</h1> <p> Письмо было отправлено. Пожалуйста, проверьте свою электронную почту, чтобы сбросить пароль. </p> |
Теперь на страницу Login.cshtml, добавим ссылку для сброса пароля:
1 2 3 |
<div> <a asp-controller="Account" asp-action="ForgotPassword">Забыли пароль?</a> </div> |
Запустим приложение и проверим его работу. На данном этапе, пользователь может нажать по ссылке “Забыли пароль?”, ввести свой емейл адрес.
После этого на его почту должна прийти ссылка, для сброса пароля (еще недействующая):
Теперь пришло время позволить пользователю создать свой новый пароль.
Определение действий для сброса пароля
Когда пользователь нажмет на ссылку в письме о сбросе пароля, он попадет на страницу, где сможет создать новый пароль.
Ссылка направляет пользователей на действие ResetPassword контроллера Account. Поэтому добавим действие ResetPassword вместе с другим действием под названием ResetPasswordConfirmation в контроллер Account:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
[AllowAnonymous] public IActionResult ResetPassword(string token, string email) { var model = new ResetPassword { Token = token, Email = email }; return View(model); } [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<IActionResult> ResetPassword(ResetPassword resetPassword) { if (!ModelState.IsValid) return View(resetPassword); var user = await _userManager.FindByEmailAsync(resetPassword.Email); if (user == null) return RedirectToAction(nameof(ResetPasswordConfirmation)); var resetPassResult = await _userManager.ResetPasswordAsync(user, resetPassword.Token, resetPassword.Password); if (!resetPassResult.Succeeded) { foreach (var error in resetPassResult.Errors) ModelState.AddModelError(error.Code, error.Description); return View(); } return RedirectToAction(nameof(ResetPasswordConfirmation)); } public IActionResult ResetPasswordConfirmation() { return View(); } |
Метод действия ResetPassword в версии HTTP GET вызывается, когда пользователь нажимает на ссылку сброса пароля в своем письме. Работа этого метода действия заключается в получении токена и адреса электронной почты и привязке их к представлению.
Затем пользователь заполняет новый пароль и пароль подтверждения на странице View (т.е. ResetPassword.cshtml) и нажимает кнопку для сохранения. При этом вызывается HTTP POST-версия метода действия ResetPassword. Этот метод действия получает новый пароль, электронную почту пользователя и токен через привязку к модели.
Код, создающий новый пароль пользователя, следующий:
1 |
var user = await _userManager.FindByEmailAsync(resetPassword.Email); |
Далее нам нужно создать класс ResetPassword.cs в папке Models со следующим кодом:
1 2 3 4 5 6 7 8 9 10 11 |
public class ResetPassword { [Required] public string Password { get; set; } [Compare("Password", ErrorMessage = "Пароль и пароль подтверждения не совпадают.")] public string ConfirmPassword { get; set; } public string Email { get; set; } public string Token { get; set; } } |
Теперь определим представления для установки пароля, в папке Views – Account.
Добавим представление ResetPassword.cshtml, со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@model ResetPassword @{ ViewData["Title"] = "Сброс пароля"; } <h1 class="bg-info text-white">Сброс пароля</h1> <div class="text-danger" asp-validation-summary="All"></div> <form asp-action="ResetPassword" method="post"> <div class="form-group"> <label asp-for="Password"></label> <input asp-for="Password" class="form-control" /> </div> <div class="form-group"> <label asp-for="ConfirmPassword"></label> <input asp-for="ConfirmPassword" class="form-control" /> </div> <input type="hidden" asp-for="Email" class="form-control" /> <input type="hidden" asp-for="Token" class="form-control" /> @Html.AntiForgeryToken() <button class="btn btn-primary" type="submit">Подтвердить</button> </form> |
Добавим представление ResetPasswordConfirmation.cshtml, со следующим содержимым:
1 2 3 4 5 6 7 8 9 |
@{ ViewData["Title"] = "Подтверждение сброса пароля"; } <h1>Подтверждение сброса пароля</h1> <p> Пароль был восстановлен. Пожалуйста, <a asp-controller="Account" asp-action="Login">авторизуйтесь.</a> </p> |
В представлении ResetPassword пользователи будут создавать свои новые пароли, а в представлении ResetPasswordConfirmation будет отображаться подтверждающее сообщение для пользователей после успешной смены пароля.
Запустите приложение и попробуйте сбросить пароль. Надеюсь, вам понравилась эта статья. Вы можете скачать исходный код в моем репозитории — Github.
Поделитесь вашим опытом в комментариях, как вы организуете восстановление пароля в Asp.Net Core приложениях?
Так же вам может быть интересна предыдущая статья — Необработанные строковые литералы или же статья на тему:
Вы начинающий программист, который хочет изучить все тонкости языка C#?
Пройдите наш тест на 13 вопросов, чтобы узнать, как много вы знаете на самом деле!
C# Braincheck |
Вы хотите научится писать код на языке программирования C#?
Создавать различные информационные системы, состоящие из сайтов, мобильных клиентов, десктопных приложений, телеграмм-ботов и т.д.
Переходите к нам на страницу Dijix и ознакомьтесь с условиями обучения, мы специализируемся только на индивидуальных занятиях, как для начинающих, так и для более продвинутых программистов. Вы можете взять как одно занятие для проработки интересующего Вас вопроса, так и несколько, для более плотной работы. Благодаря личному кабинету, каждый студент повысит качество своего обучения, в вашем распоряжении:
- Доступ к пройденному материалу
- Тематические статьи
- Библиотека книг
- Онлайн тестирование
- Общение в закрытых группах
Живи в своем мире, программируй в нашем.