آموزش احراز هویت در Asp.net Core

آموزش احراز هویت در Asp.net Core

خواندن این مطلب

8 دقیقه

زمان میبرد!

مقدمه

سلام خدمت همه کاربران عزیز نونویسان در این آموزش قصد دارم بهتون یاد بدم که به چه شکل یک احراز هویت کامل برای سایت Asp.net Core خود ایجاد بکنید و سورس کد ها هم برای شما قرار میدهم پس تا آخر آموزش احراز هویت در Asp.net Core همراه من باشید.
در صورت تمایل میتوانید مقاله مدیریت خطای ۴۰۴ در Asp.net Core را نیز مشاهده کنید.

ثبت نام در Asp.net Core همراه سورس

این آموزش دارای بروزرسانی است پس هیچ نگران نباشید.

قصد داریم برای راحتی کاربران در صفحه ثبت نام سه فیلد قرار بدهیم ایمیل، رمز عبور و تکرار رمز عبور پس کار را مرحله به مرحله شروع میکنیم اولین قدم ساخت Controller است برای نوشتن کد های لازم به همین علت AccountController را ایجاد میکنید و در مرحله اول کد های لازم برای get را مینویسیم.

				
					[HttpGet("Register")]
public IActionResult Register()
{
    return View();
}
				
			

شما به دو روش میتوانید به Controller خود مسیر بدهید اولیش این هست که مثل کد بالا جلوی HttpGet بنویسید و دومین روش استفاده از Route به شکل زیر است.

				
					[Route("Register")]
				
			

بعد از اینکه HttpGet را نوشتید نوبت ساخت View است روی Action خود کلیک راست کنید و AddView را بزنید و دقت کنید که باید از نوع Razor View باشد.

دقت کنید نباید مدل خود را به ویو متصل بکنید چون چیز های اضافی دارد که شما نیاز ندارید و فقط سه بخش را لازم دارید پس یک ViewModel میسازید مانند کد زیر

				
					public class RegisterViewModel
    {
        [Display(Name = "ایمیل")]
        [MaxLength(100, ErrorMessage = "{0} نمیتواند بیشتر از {۱} کاراکتر باشد")]
        [EmailAddress(ErrorMessage = "ایمیل وارد شده معتبر نمیباشد")]
        [Required(ErrorMessage = "لطفا {۰} خود را وارد کنید")]
        public string Email { get; set; }

        [Display(Name = "کلمه عبور")]
        [Required(ErrorMessage = "لطفا {۰} خود را وارد کنید")]
        [MaxLength(100, ErrorMessage = "{0} نمیتواند بیشتر از {۱} کاراکتر باشد")]
        public string Password { get; set; }

        [Display(Name = "کلمه عبور")]
        [Required(ErrorMessage = "لطفا {۰} خود را وارد کنید")]
        [MaxLength(100, ErrorMessage = "{0} نمیتواند بیشتر از {۱} کاراکتر باشد")]
        [Compare("Password", ErrorMessage = "کلمه های عبور یکسان نیستند")]
        public string RePassword { get; set; }
    }

    public enum RegisterResult
    {
        Success,
        EmailExist
    }
				
			

RegisterViewModel که همان ViewModel ما است و به ویو متصل میشود و RegisterResult برای مدیریت خطا است تمام حالت های ممکن را در اینجا مینویسیم تا مدیریت بکنیم و به کاربر خطا های لازم را نمایش بدهیم حالا نوبت اتصال View به این مقادیر است پس وارد ویو میشویم و به شکل زیر View را به ViewModel متصل میکنیم.

				
					@model BugFixer.Domain.ViewModels.Account.RegisterViewModel
				
			

با این کد در اصل داریم میگیم که model صفحه همان RegisterViewModel است این این را ابتدای ویو Register مینویسیم حالا نوبت اتصال فیلد های ایمیل، رمز عبور و تکرار رمز عبور به مدل است که طبق کد زیر انجام میشود.

				
					<form asp-action="Register" asp-controller="Account" method="post">
    <div>
        <span><i class="icon-mail-envelope"></i> پست الکترونیک </span>
        <input type="email" asp-for="Email">
    </div>
    <span class="Error-Style" asp-validation-for="Email"></span>
</form>
				
			

بیاین تا کد بالا رو بهتون توضیح بدهم اول یک form درست میکنیم که method آن را روی Post قرار میدهیم و به Action متصل میکنیم حالا نوبت اتصال تک تک مقادیر مانند ایمیل است که من فقط Email را متصل کردم بقیه موارد یکسان هستند.

داخل input یک asp-for ایجاد میکنیم تا اینکه تعیین بکنیم این فیلد به کدام Property متصل شود و در ادامه آن را به Email وصل میکنیم.

span هم برای نمایش ارور های لازم در صفحه است که آن را هم با asp-validation-for به Email متصل میکنیم و بقیه فیلد ها هم به این شکا درست میکنیم حالا نوبت نوشتن کد های لازم است؛ از آنجایی که ما با ایمیل سر و کار داریم نباید کاربر بتواند با یک ایمیل دو حساب کاربری ایجاد بکند پس اول بررسی میکنیم که ایمیل وارد شده تکراری نباشد پس یک Interface ایجاد میکنیم تا این نیاز را داخل آن بنویسیم؛ نام آن را IAccountService میگذاریم که تمام قوانین مربوط به کاربران را اینجا پیاده سازی بکنیم.

حالا برای ثبت نام کاربر دو سرویس نیاز داریم یکی که بررسی کنیم کاربر ایمیل تکراری وارد نکند و دوم برای ثبت نام کاربر.

دو قطعه کد خود را در IAccountService که یک Interface است بنویسید اولی برای بررسی ایمیل تکراری و دومی برای ثبت نام کاربر است.

				
					Task<bool> IsExistEmail(string email);
    Task<RegisterResult> RegisterUser(RegisterViewModel register);
				
			

حالا یک کلاس به اسم AccountService ایجاد میکنیم تا از IAccountService ارث بری بکند که بتوانیم برای نیاز هایی که ایجاد کردیم کدنویسی بکنیم ولی قبل از همه این ها نیاز داریم به context خود دسترسی داشته باشیم پس کد زیر را مینویسیم در ابتدای کلاس مورد نظر.

				
					private BugFixerContext _context;
    public UserService(BugFixerContext context)
    {
        _context = context;
    }
				
			

حالا نوبت Implementation کردن است پس اول میریم به سراغ کد بررسی تکراری نبودن ایمیل وارد شده.

				
					public async Task<bool> IsExistEmail(string email)
    {
        return await _context.Users.AnyAsync(e => e.Email == email);
    }
				
			

حالا که بررسی کردیم وقتی کاربر دارد ایمیل خود را وارد میکند تکراری نباشد باید بریم سراغ اینکه کاربر را در سایت خود ثبت نام بکنیم پس نوبت Implement کردن کد دوم است که به شکل زیر است.

				
					public async Task<RegisterResult> RegisterUser(RegisterViewModel register)
    {
        if (await IsExistEmail(register.Email.Trim().ToLower()))
        {
            return RegisterResult.EmailExist;
        }
        var hashPassword = PasswordHelper.EncodePasswordMd5(register.Password);
        var user = new User()
        {
            Avatar = "UserImage.jpg",
            Password = hashPassword,
            Email = register.Email.Trim().ToLower(),
            EmailActiveCode = CodeGenerator.CreateActivationCode(),
        };
        await _context.AddAsync(user);
        await _context.SaveChangesAsync();

        #region Send Activation Email



        #endregion

        return RegisterResult.Success;
    }
				
			

کد بالا کامل مشخص است بجز دو بخش HashPassword و CodeGenerator که اولی برای برای رمز کردن رمز کاربران برای امنیت بیشتر است و دومی یک عبارت غیرقابل تکراری ایجاد میکند برای اینکه کاربر حساب خود را در آینده با آن فعال بکند که کد های آن ها را نیز براتون قرار میدهم.

کد زیر برای Hash کردن رمز کاربران است.

				
					public class PasswordHelper
    {
        public static string EncodePasswordMd5(string pass) //Encrypt using MD5   
        {
            Byte[] originalBytes;
            Byte[] encodedBytes;
            MD5 md5;
            //Instantiate MD5CryptoServiceProvider, get bytes for original password and compute hash (encoded password)   
            md5 = new MD5CryptoServiceProvider();
            originalBytes = ASCIIEncoding.Default.GetBytes(pass);
            encodedBytes = md5.ComputeHash(originalBytes);
            //Convert encoded bytes back to a 'readable' string   
            return BitConverter.ToString(encodedBytes);
        }
    }
				
			

کد زیر نیز برای این اس که یک عبارت غیر تکراری برای هر حساب کاربری ایجاد کند تا بتوانیم کار های مورد نیاز را انجام بدهیم که با استفاده از Guid کار میکند.

				
					public static class CodeGenerator
    {
        public static string CreateActivationCode()
        {
            return Guid.NewGuid().ToString("N");
        }
    }
				
			

حالا که کد های مورد نیاز برای بررسی ایمیل و ثبت نام نوشتیم نوبت این است که وارد Controller شویم و در Action ثبت نام کد ها را فراخوانی کنیم پس کد های زیر را در Action مورد نظر مینویسیم.

				
					[HttpPost("Register")]
    public async Task<IActionResult> Register(RegisterViewModel register)
    {
        if (!ModelState.IsValid)
        {
            return View(register);
        }
        var result = await _userService.RegisterUser(register);
        switch (result)
        {
            case RegisterResult.EmailExist:
                    break;
            case RegisterResult.Success:
                    break;
        }
        return View(register);
    }
				
			

حالا نوبت این هستش که ما برای هرکدام از رویداد ها یک پیغام مناسب نمایش بدهیم برای مثال اگه ثبت نام با موفقیت انجام شد پیغام موفقیت را به کاربر نمایش بدهیم و بهترین حالت هم استفاده از TempData هستش و برای اینکه کار ما راحت تر شود در BaseController به شکل زیر تعریف میکنیم.

قبل نمایش کد ها بهتون بگم که BaseController برای این است که دیگر Controller ها از او ارث بری کنند تا کد هایمان را یکبار بنویسیم و در دیگر Controller ها استفاده کنیم مانند همین پیغام خطا که به شکل زیر است.

				
					public class BaseController : Controller
    {
        public static string SuccessMessage = "SuccessMessage";
        public static string InfoMessage = "InfoMessage";
        public static string WarningMessage = "WarningMessage";
        public static string ErrorMessage = "ErrorMessage";
    }
				
			

برای این داخل Controller نوشتیم پیغام های مورد نظر رو چون که همه Controller ها از این BaseController ارث بری میکنند و همه جا به این مقادیر دسترسی داریم.

حالا که پیغام های خود را تعیین کردیم نوبت این است که نمایش بدهیم اول به سراغ Switch میرویم که داخل AccountController بود.

				
					public async Task<IActionResult> Register(RegisterViewModel register)
    {
        if (!ModelState.IsValid)
        {
            return View(register);
        }
        var result = await _userService.RegisterUser(register);
        switch (result)
        {
            case RegisterResult.EmailExist:
            TempData[ErrorMessage] = "ایمیل وارد شده در سایت وجود دارد.";
            break;
            case RegisterResult.Success:
            TempData[ErrorMessage] = "عملیات ثبت نام با موفقیت انجام شد.";
            return RedirectToAction("Login", "Account");
        }
            return View(register);
    }
				
			

در کدی که بالاتر بود پیغامی جهت نمایش نبود ولی اینجا پیام مورد نظر با TempData نمایش داده میشود حالا باید برای اینکه بتوانیم با TempData پیغام مورد نظر را نمایش دهیم SweetAlert را به پروژه خود اضافه بکنیم که یک CDN نیاز دارد ولی من کار را برای شما راحت کردم از طریق دکمه زیر فایل SweetAlert را دانلود کنید و سند js را داخل wwwroot خود قرار دهید.

بعد از اینکه فایل JavaScript را داخل پوشه wwwroot قرار دادید باید آن را به قالب خود رفرنس دهید البته داخل Footer قالب خود قرار دهید.

در ادامه نوبت ساخت یک Partial View است برای انجام تنظیمات مربوط به نمایش پیغام که داخل Shared ایجاد شود.

				
					@if (TempData["ErrorMessage"] != null)
{ <script type="litespeed/javascript">swal({title:"پیام سیستم",text:"@TempData["ErrorMessage"]",icon:"error",button:"باشه",})</script> }

@if (TempData["SuccessMessage"] != null)
{ <script type="litespeed/javascript">swal({title:"پیام سیستم",text:"@TempData["SuccessMessage"]",icon:"success",button:"باشه",})</script> }

@if (TempData["InfoMessage"] != null)
{ <script type="litespeed/javascript">swal({title:"پیام سیستم",text:"@TempData["InfoMessage"]",icon:"info",button:"باشه",})</script> }

@if (TempData["WarningMessage"] != null)
{ <script type="litespeed/javascript">swal({title:"پیام سیستم",text:"@TempData["WarningMessage"]",icon:"warning",button:"باشه",})</script> }
				
			

این تنظیمات را داخل Partial View ایجاد شده در Shared بنویسید که برای فارسی سازی SweetAlert است.

حالا Partial را داخل Layout خود رفرنس میدهیم.

				
					<partial name="_Notification" />
				
			

دقت کنید که در بخش Name باید نامی که برای Partial خود انتخاب کردید را قرار بدهید همان که تنظیمات را داخلش نوشتیم.

الان دیگه SweetAlert با موفقیت به پروژه اضافه شده ولی اگه توی پروژه مشاهده بکنید پیغام شما به صورت کد نمایش داده میشود و فارسی نیست برای حل این مشکل وارد فایل Program.cs شوید و زیر تنظیمات مربوط به Context کد زیر را بنویسید.

				
					builder.Services.AddSingleton<HtmlEncoder>(
    HtmlEncoder.Create(allowedRanges: new[] { UnicodeRanges.All }));
				
			

تا به اینجا در آموزش احراز هویت در Asp.net Core ایجاد یک عملیات ثبت نام را یاد گرفتید در مرحله بعد ارسال ایمیل فعالسازی رو بهتون یاد میدهم.

گوگل ریکپچا در Asp.net Core همراه سورس

برای اضافه کردن گوگل ریکپچا به پروژه اول باید وارد سایتش بشیم که برای این کار Google Recaptcha رو جستجو میکنیم و وارد اولین نتیجه میشیم.

سایت گوگل ریکپچا

بعد از این که وارد سایت شدید از بخش بالایی سایت گزینه v3 Admin Console رو میزنید تا وارد صفحه جدید بشید در اونجا از منوی سمت راست در بالای صفحه روی علامت به علاوه کلیک کنید تا وارد صفحه زیر شوید.

افزودن اطلاعات سایت در گوگل ریکپچا

در این بخش اطلاعات خواسته شده را وارد کنید.

در بخش Label که یک اسم انتخاب میکنید و در مرحله بعد نسخه Google Recaptcha ریکپچا خود را انتخاب میکنید که ما ورژن ۳ را انتخاب کردیم و در بخش Domains دامنه های خود را وارد میکنید.

من در بخش Domains لوکال هاست را نوشتم چون فعلا دامنه ای خریداری نکردم شما آدرس دامنه خود را وارد کنید و اگر هنوز دامنه ای خریداری نکردید و مثل من روی ویژوال استودیو به صورت LocalHost کار میکنید در این بخش همان لوکال هاست را وارد کنید در آخرین مرحله قوانین را Accept میکنیم و روی دکمه SUBMIT کلیک میکنیم تا وارد صفحه زیر شویم.

Site Key And Secret Key In Google Recaptcha

همیشه اطلاعاتی از این قبیل را داخل appsetting.json قرار میدهیم.

وارد کردن اطلاعات کپچا در appsetting
				
					"GoogleReCaptcha:SiteKey": "6LfmbeUhAAAAAM0DRyufn0ulGgKLdtnZQozki0ke",
  "GoogleReCaptcha:SecretKey": "6LfmbeUhAAAAAKiIaGyve_vToNGEMUvEH0HQwpm2"
				
			

همانطور که در تصویر میبینید کلید ها را وارد کنید میتوانید کد های بالا را کپی کنید و بعد کلید های خود را جایگزین آن بکنید.

در مرحله بعد باید یک بسته از Nuget دانلود کنیم به اسم GoogleReCaptcha.V3.

بعد از دانلود بسته مورد نظر وارد program.cs میشیم و کد زیر را در بالای تنظیمات مربوط به context اضافه میکنیم.

				
					builder.Services.AddHttpClient<ICaptchaValidator, GoogleReCaptchaValidator>();
				
			

چون توی صفحات زیادی از گوگل ریکپچا استفاده میکنیم یبار براش ویو مدل میسازیم که هرجا خواستیم فقط فراخوانیش بکنیم پس یک ViewModel درست میکنیم و به شکل زیر فقط یک Property داخل آن قرار میدیم.

				
					public class GoogleReCaptchaViewModel
    {
        public string Captcha { get; set; }
    }
				
			

حالا هرجایی که میخوایم بهش Recaptcha رو اضافه کنیم باید از این ویو مدل ارث بری کنه برای مثال کلاس RegisterViewModel باید از GoogleReCaptchaViewModel ارث بری بکنه.

حالا وارد Controller ثبت نام خود میشویم تا در constructor پکیج نصب شده را inject بکنیم.

				
					private IUserService _userService;
private ICaptchaValidator _captchaValidator;
public AccountController(IUserService userService, ICaptchaValidator captchaValidator)
{
    _userService = userService;
    _captchaValidator = captchaValidator;
}
				
			

بعد از inject کردن ReCaptcha باید وارد متد Post ثبت نام بشیم و کد زیر را قبل از همه کد ها وارد کنیم.

				
					if (!await _captchaValidator.IsCaptchaPassedAsync(register.Captcha))
    {
        TempData[ErrorMessage] = "اعتبار سنجی Captcha با خطا مواجه شد";
        return View(register);
    }
				
			

یعد از وارد کردن کد بالا که برای بررسی تایید شدن کپچا هست باید وارد View ثبت نام بشیم تا از سمت ویو هم تایید شدن Captcha را بررسی بکنیم پس به شکل زیر یک input با تایپ hidden ایجاد میکنیم و آن را به Captcha متصل میکنیم.

				
					<input type="hidden" asp-for="Captcha" />
				
			

حالا باید یک Scrtip برای گوگل ریکپچا بسازیم تا هرجا که نیاز داشتیم بتوانیم به راحتی آن را در ویو ها استفاده بکنیم.

				
					@inject IConfiguration _configuration <script type="litespeed/javascript" data-src="https://www.google.com/recaptcha/api.js?render=@_configuration["GoogleReCaptcha:SiteKey"]"></script> <script type="litespeed/javascript">grecaptcha.ready(function(){window.grecaptcha.execute('@_configuration["GoogleReCaptcha:SiteKey"]',{action:'home'}).then(function(token){$("#Captcha").val(token)})})</script>
				
			

حالا باید به شکل زیر Script را در ویو Register رفرنس بدیم.

				
					@section Scripts{
    <partial name="_CaptchaScripts" />
}
				
			

در این بخش آموزش احراز هویت در Asp.net Core یاد گرفتید که GoogleReCaptcha را به پروژه خود اضافه بکنید اگه سوالی داشتید در بخش تماس با ما یا کامنت مطرح بکنید.

به مقاله امتیاز دهید

درباره نویسنده



نظرات کاربران



  • آواتار زهیر صفری
    زهیر صفری
    مهمان

    با سلام
    سرویس GoogleReCaptchaValidator این رو تعریف نکردید بهتر بود سورس در گیتهاب یا فایل ضمیمه میکردید ممنون میشم سورس برای دانلود بزارید

    • آواتار محمد مهدی زارع
      محمد مهدی زارع
      مدیر سایت

      با سلام خدمت شما کاربر عزیز
      ما سرویسی با این عنوان تعریف نکردیم چون این Interface در بسته دانلود شده به نام GoogleReCaptcha.V3 موجود هست و صرفا برای اینکه بتونیم ازش استفاده بکنیم در startup قرارش دادیم.
      ولی در بروزرسانی این مقاله هم اطلاعات جدیتری اضافه خواهد شد و هم در صورت نیاز تمامی بخش ها در قالب یک فایل zip در انتهای مقاله قرار میگیرند.

دیدگاهتان را بنویسید

مطالب مرتبط