[ Полезный рекламный блок ]
Попробуйте свои силы в игре, где ваши навыки программирования на 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; } } |
Як виконувати надсилання листа, отримувати паролі додатків, детально розглядається в статті:
Тепер визначимо подання для скидання пароля в папці 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#?
Створювати різні інформаційні системи, що складаються з сайтів, мобільних клієнтів, десктопних додатків, телеграм-ботів тощо.
Переходьте до нас на сторінку Dijix і ознайомтеся з умовами навчання, ми спеціалізуємося тільки на індивідуальних заняттях, як для початківців, так і для просунутих програмістів. Ви можете взяти як одне заняття для опрацювання питання, що вас цікавить, так і кілька, для більш щільної роботи. Завдяки особистому кабінету, кожен студент підвищить якість свого навчання, у вашому розпорядженні:
- Доступ до пройденого матеріалу
- Тематичні статті
- Бібліотека книг
- Онлайн тестування
- Спілкування в закритих групах