Refresh

Quên mật khẩu và reset mật khẩu trong .Net Core

   Trong bài viết này, chúng ta sẽ xem cách đặt lại mật khẩu thông qua trang quên mật khẩu ASP.NET Core. Thêm một liên kết hành động trên trang đăng nhập nếu người dùng quên mật khẩu của mình. Liên kết chuyển hướng người dùng đến trang bên dưới nơi người dùng có thể nhận liên kết đặt lại trên ID email đã đăng ký. Lưu ý: Người dùng phải là người dùng đã đăng ký. Đây là cách trang mật khẩu quên trông. Người dùng cần nhập ID email đã đăng ký và hợp lệ mà liên kết đặt lại sẽ được gửi.       

                        

    Đầu tiên chúng ta xây dựng source như bên dưới để chia nhỏ các thành phần trong code sẽ giúp chúng ta quản lí code gọn gàng hơn, ...

Bước 1: Trong file IAuthenticateRepository thì chúng ta tạo interface


using Core.Applications.DTOs;
using Core.Applications.DTOs.Authenticate;
using System.Threading.Tasks;

namespace Core.Applications.Interface.IRepositories
{
    public interface IAuthenticateRepository

    {
        Task ForgetPasswordAsync(string email);
        Task ResetPasswordAsync(ResetPasswordDto request);
    }
}

 

Bước 2: IAuthenticateService


using Core.Applications.DTOs;
using Core.Applications.DTOs.Authenticate;
using System.Threading.Tasks;

namespace Core.Applications.Service
{
    public interface IAuthenticateService
    {
        Task ForgetPasswordAsync(string email);
        Task ResetPasswordAsync(ResetPasswordDto request);
    }
}

 

Bước 3:  AuthenticateService


public async Task ForgetPasswordAsync(string email)
        {
            var result = await _authenticateRepository.ForgetPasswordAsync(email);
            return result;
        } 
public async  Task ResetPasswordAsync(ResetPasswordDto request)
        {
            var result =await   _authenticateRepository.ResetPasswordAsync(request);
            return result;
        }


Bước 4:  AuthenticateRepository


public async Task ForgetPasswordAsync(string email)
        {
            var user = await _context.Users.FirstOrDefaultAsync(x => x.Email == email);
            if (user == null) throw new ApiException("Email invalid.");
            user.ResetPassword = Guid.NewGuid().ToString();
            _context.Users.Update(user);
            await _context.SaveChangesAsync();
            var emailRequest = new EmailRequest()
            {
                Body = $"token={user.ResetPassword}&email={email}&userId={user.Id}",
                To = email,
                Subject = "Reset your password",
            };

            await _emailService.SendAsync(emailRequest);
            return emailRequest;

        }
        public async Task ResetPasswordAsync(ResetPasswordDto request)
        {
            // Tìm user tồn tài không // tìm theo email // email duy nhất rồi

            var user = await _context.Users.FirstOrDefaultAsync(x => x.Email == request.Email);
            if (user == null) throw new ApiException("Email invalid.");
            if(user.Id == request.Id && user.Email == request.Email && user.ResetPassword == request.Token)

            {
                if(request.NewPassword != request.ConfirmPassword) throw new ApiException("Password does not match.");

                // bằng hết cho đổi pass

                int salt = 12;
                string passwordHash = BCrypt.Net.BCrypt.HashPassword(request.NewPassword, salt);
                user.Password = passwordHash;
                _context.Users.Update(user);
                await _context.SaveChangesAsync();
            } 
            else
            {
                throw new ApiException("Invalid.");
            }
            return request;
        }
        

 

Bước 5:  Controller .


 [HttpPost("forget-password")]
        public async Task ForgetPasswordAsync(string email)
        {
            try
            {
                await _authenticateService.ForgetPasswordAsync(email);
                return Ok();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        [HttpPost("reset-password")]
        public async Task ResetPasswordAsync([FromForm]ResetPasswordDto resetPasswordDto)
        {
            try
            {
                await _authenticateService.ResetPasswordAsync(resetPasswordDto);
                return Ok("Ok");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        

 

Ở phần DTO tạo 2 class


namespace Core.Applications.DTOs
{
    public class EmailRequest
    {
        public string To { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public string From { get; set; }
    }
}

 

Nếu chúng ta xữ lí nhiều email cùng 1 lúc thì dùng EmailMultiRequest


using System.Collections.Generic;

namespace Core.Applications.DTOs
{
    public class EmailMultiRequest
    {
        public List To { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public string From { get; set; }      
    }
}

 

Ở bước này chúng ta tạo một class DTOs để chứa những filed output ra


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Applications.DTOs.Authenticate
{
    public class ResetPasswordDto
    {
        public Guid Id { get; set; }
        public string Email { get; set; }
        public string Token { get; set; }
        public string NewPassword { get; set; }
        public string ConfirmPassword { get; set; }
    }
}

 

Ở bước này chúng ta tạo một class DTOs để chứa những filed out


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Applications.DTOs.Authenticate
{
    public class ResetPasswordDto
    {
        public Guid Id { get; set; }
        public string Email { get; set; }
        public string Token { get; set; }
        public string NewPassword { get; set; }
        public string ConfirmPassword { get; set; }
    }
}

 

Bước 7: Ở tầng Interface


using Core.Applications.DTOs;
using System.Threading.Tasks;

namespace Core.Applications.Interface
{
    public  interface IEmailService
    {
        Task SendAsync(EmailRequest request);
        Task SendMultiAsync(EmailMultiRequest request);
    }
}

 

Và viết class implement cho tầng này :


using Core.Applications.DTOs;
using Core.Applications.Exceptions;
using Core.Applications.Interface;
using Core.Domain.Settings;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MimeKit;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using MailKit.Security;

namespace Infrastructure.Shared.Services
{
    public class EmailService : IEmailService
    {
        public MailSetting MailSettings { get; }
        public ILogger Logger { get; }
        public EmailService(IOptions mailSettings, ILogger logger)
        {
            MailSettings = mailSettings.Value;
            Logger = logger;
        }
        public async Task SendAsync(EmailRequest request)
        {
            try
            {
                // create message
                var email = new MimeMessage
                {
                    Sender = MailboxAddress.Parse(request.From ?? MailSettings.EmailFrom)
                };
                email.To.Add(MailboxAddress.Parse(request.To));
                email.Subject = request.Subject;
                var builder = new BodyBuilder
                {
                    HtmlBody = request.Body
                };
                email.Body = builder.ToMessageBody();
                using var smtp = new SmtpClient();
                await smtp.ConnectAsync(MailSettings.SmtpHost, MailSettings.SmtpPort, SecureSocketOptions.StartTls);
                await smtp.AuthenticateAsync(MailSettings.SmtpUser, MailSettings.SmtpPass);
                await smtp.SendAsync(email);
                await smtp.DisconnectAsync(true);
            }
            catch (System.Exception ex)
            {
                Logger.LogError(ex.Message, ex);
                throw new ApiException(ex.Message);
            }
        }
        public async Task SendMultiAsync(EmailMultiRequest request)
        {
            try
            {
                // create message
                var email = new MimeMessage
                {
                   Sender = MailboxAddress.Parse(request.From ?? MailSettings.EmailFrom)
                };
                foreach (var item in request.To)
                {
                    email.To.Add(MailboxAddress.Parse(item));
                }
                email.Subject = request.Subject;
                var builder = new BodyBuilder
                {
                    HtmlBody = request.Body
                };
                email.Body = builder.ToMessageBody();
                using var smtp = new SmtpClient();
                await smtp.ConnectAsync(MailSettings.SmtpHost, MailSettings.SmtpPort, SecureSocketOptions.StartTls);
                await smtp.AuthenticateAsync(MailSettings.SmtpUser, MailSettings.SmtpPass);
                await smtp.SendAsync(email);
                await smtp.DisconnectAsync(true);
            }
            catch (System.Exception ex)
            {
                Logger.LogError(ex.Message, ex);
                throw new ApiException(ex.Message);
            }
        }
    }
}


Ở phần Setting thì chúng ta tạo file


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Domain.Settings
{
   public class MailSetting
    {
        public string EmailFrom { get; set; }
        public string SmtpHost { get; set; }
        public int SmtpPort { get; set; }
        public string SmtpUser { get; set; }
        public string SmtpPass { get; set; }
        public string DisplayName { get; set; }
    }
}

 

Sau đó thì đăng kí ở file Infrastructure.Shared và qua startup gọi lại

using Core.Applications.Interface;
using Core.Applications.Interface.IRepositories;
using Core.Domain.Settings;
using Infrastructure.Persistence.Repositories;
using Infrastructure.Shared.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Infrastructure.Shared
{
    public static class ServiceRegistration
    {
        public static void AddSharedInfrastructure(this IServiceCollection services, IConfiguration _config)
        {
            services.Configure(_config.GetSection("MailSettings"));
            services.AddTransient();
            services.AddTransient();
            services.AddTransient();
        }
    }
}

 

Ở phần appsetting chúng ta set email .


  "MailSettings": {
    "EmailFrom": "lehieu.qrt@gmail.com",
    "SmtpHost": "smtp.gmail.com",
    "SmtpPort": 587,
    "SmtpUser": "lehieu.qrt@gmail.com",
    "SmtpPass": "0327547475hieu",
    "DisplayName": ""
  },

 

Chúc các bạn thành công nhé !!

2 Nhận xét

Mới hơn Cũ hơn