كيفية إعداد وتكوين ASP.NET Core Identity

-

إن ASP.NET Core Identity عبارة عن Toolkit and an APIيمكنك من خلالها إنشاء ميزات Authorization and Authentication في التطبيقات. يمكن للمستخدمين إنشاء حساب وتسجيل الدخول باستخدام اسم مستخدم وكلمة مرور. وهذا يشمل أيضًا Roles and Roles Management. يستخدم ASP.NET Core Identity قاعدة بيانات SQL Server لتخزين أسماء المستخدمين user names وكلمات المرور passwords والأدوار roles وبيانات ملف التعريف profile data.

خلونا نبدا بعمل مشروع باسم ASP.NET.Core.Identity ويكون نوع المشروع ASP.NET Core Empty


تأكد يكون framework رقم 5

تمام وحتي نتعامل مع Identity بنحتاج الى تثبيت مجموعة من packages  وهي :

  • Microsoft.AspNetCore.Identity
  • Microsoft.AspNetCore.Identity.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.SqlServer
انقر يمين فوق المشروع واختر Manage NuGet Package 


دور على packages السابقة وثبتها في المشروع(الصورة في الاسفل تم البحث عن Microsoft.AspNetCore.Identity).

بنفس الطريقة كمل الباقي.

بعد التثبيت بكون شكل المشروع :


اكيد لاحظت ان الاصدار الخاص بهذه Packages لازم يكون متوافق مع اصدار Frameworks الي بتشغل عليها. يعني اذا حاولت تثبت اي اصدار اكير من 5 بتكون النتيجة خطأ. 

بخصوص Frameworks 6. اكيد في الها دروس مستقلة بتقدر نشوف اهم المميزيات فيها.

تمام الان بعد ما ثبتنا Packages صار وقت نجهز اعدادات التطبيق .

ننتقل الى Startup Class وقم بإعداد MVC framework وconfigure Middleware التي بتكون مطلوبة للمشروع. الكود المحث الخاص ب Startup.cs هو:

// This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
           app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

اكيد بنحتاج الى تثبيت Bootstrap بهدف التحكم بتصميم Views 

حتى نثبت Bootstrap بنحتاج أولاً إنشاء مجلد جديد باسم wwwroot في المشروع، وبعد الاضافة انقر بزر الماوس الأيمن فوقه wwwroot  وحدد  Add ➤ Client-Side Library . 


من النافذة التالية نبحث عن twitter-bootstrap في مربع نص وانقر على زر التثبيت.


انشاء Views 

قم بإنشاء Views folder في المشروع ، وداخله قم بإنشاء مجلد آخر يسمى Shared folder.

انشاء ملف Layout

انقر بزر الماوس الأيمن فوق Shared folder ، وحدد Add ➤ New Item. من النافذة التالية حدد Razor Layout وانقر فوق الزر Add.


سيؤدي هذا إلى إضافة ملف Layout.cshtml_ في Shared folder وسيتم فتحه. بعد ذلك ، أضف الكود التالي إليه:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/twitter-bootstrap/css/bootstrap.css" rel="stylesheet" />
</head>
<body class="m-1 p-1">
    @RenderBody()
</body>
</html>
مثل ما تعملنا سابقا هذا الملف يستخدم لاضافة التصميم الخاص بالتطبيق بمكان واحد ويتم تطبيقه على Views الثانية (حكينا عن هذا المفهموم سابقا) .

انشاء ViewImports and ViewStart
 
انقر بزر الماوس الأيمن على مجلد Views  وحدد Add ➤ New Item. ومن الشاشة التالية حدد Razor View Imports وانقر فوق الزر Add. سيؤدي هذا إلى إضافة ملف ViewImports.cshtml_.
اضف الكود التالي الى الملف : 
@using Identity.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
الهدف من هذه الكود هو استيراد built-in tag helpers & models namespace  لـ Views.

بنفس الطريقة ، انقر بزر الماوس الأيمن فوق المجلد Views وحدد Add ➤ New Item. ومن الشاشة التالية حدد Razor View Start وانقر فوق الزر Add.
سيؤدي هذا إلى إضافة ملف ViewStart.cshtml_ وبكون الكود الأولي الو كالتالي:
@{
    Layout = "_Layout";
}
في هذا الملف يتم اضافة ملف Layout.cshtml_ الافتراضي الموجود في Share folder الي بيتم تطبيقه على جميع Views في التطبيق. الا في حال تم تحديد غير ذلك.

تمام التمام. 

طبعا ممكن تجنب اضافة هذه الملفات من البداية باختيار نوع المشروع ASP.NET Core Web App(Model-View-Controller) بحيث يتم اضافة جميع هذه الملفات من البدايه

الان دور نتعلم كيف ممكن نعمل الاعدادات الخاصة ب ASP.NET Core Identity

تتضمن عملية إعداد ASP.NET Core Identity إنشاء التالي :
  • model classes
  • configuration changes
  • controllers
  • actions
بهدف توفير الدعم لعمليات authentication and authorization.

انشاء User Class
 
الهدف من هذا User class هو تحديد المستخدمين للتطبيق. ويتم تخزين هؤلاء المستخدمين في قاعدة البيانات. من المهم اشتقاق User class من IdentityUser class الي بتكون موجوده في Microsoft.AspNetCore.Identity namespace

وحتي نعمل هذا class لازم نعمل folder باسم Models في المشروع وداخل هذا Folder بنضيف class  باسم AppUser  وبكون شكل هذا class كالتالي: 
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ASP.NET.Core.Identity.Models
{
    public class AppUser : IdentityUser
    {
    }
}
لاحظ ان في هاذ class ما اضفنا أي property or method. وذلك لأن IdentityUser.cs class توفر بعض الخصائص مثل
user name, e-mail, phone number, password hash, role memberships 
وما إلى ذلك.
واكيد اذا كنا بحاجة الى غير ذلك يمكن اضافتها. 
في الجدول التالي ذكرنا اهم properties  الخاصة ب IdentityUser class 

اسم properties  الوصف
Id
يحتوي على Unique Id  للمستخدم
UserName
يحتوي على اسم المستخدم الخاص بالمستخدم.
Claims
تقوم هذه الخاصية بإرجاع clams للمستخدم
Email
يحتوي على البريد الإلكتروني للمستخدم.
PasswordHash
يحتوي على hash  لكلمة مرور المستخدم.
PhoneNumber
تقوم بإرجاع رقم الهاتف للمستخدم.
Roles
تقوم بإرجاع جميع الأدوار للمستخدم.
SecurityStamp
يحتوي على قيمة يتم تغييرها كلما تم تغيير هوية المستخدم. على سبيل المثال تغيير كلمة المرور أو رقم الهاتف ، إلخ.
انشاء DB Context Class
في هذا class يتم التعامل مع قواعد البيانات وتسمى DB Context Class  أيضًا باسم Database Context Class بحيث يتم تعريف الجداول المطلوب التعامل معها داخل هذا class ويمكن اجراء العمليات عليها بكل سهولة مثل الاضافة والحذف والتعديل ... الح. 
 
يتم اشتقاق DB Context Class من IdentityDbContext ويستخدم الرمز T للتعامل مع الجداول في المشروع.

في هذا المثال بنشتغل على User class وتذكر أنو قمنا بتعريف User class باسم AppUser.cs في القسم أعلاه.
تمام الان نضيف هذا Class لذا خلونا نعمل مجلد جديد باسم Data ونضيف class داخل هذا المجلد باسم AppIdentityDbContext وبعدها بنضيف الكود التالي : 
using ASP.NET.Core.Identity.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ASP.NET.Core.Identity.Data
{
    public class AppIdentityDbContext : IdentityDbContext<AppUser>
    {
        public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options) : base(options) { }
    }
}
لاحظ ، كمان ما اضفنا أي property أو method إلى هذا class، وذلك لأن هذا class الفارغ يرث من
IdentityDbContext <AppUser> 
ولذا فهي تحصل على جميع methods and properties الخاصة ب AppUser .

تمام الان دور نعرف كيف بنعمل Database Connection String

يتم تخزين Database Connection string ، التي تحتوي على اسم قاعدة البيانات واسم المستخدم وكلمة المرور للاتصال بقاعدة البيانات ، في الغالب في ملف appsettings.json.  يجب إنشاء هذا الملف في المشروع.
اذا كان الملف appsettings.json غير موجود في المشروع، انقر بزر الماوس الأيمن فوق اسم المشروع في وحدد Add ➤ New Item، ثم من الشاشة التالية حدد App Settings File ، وانقر فوق الزر إضافة.
وفي هذا المف اضف الكود التالي : 
{"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" }}, "ConnectionStrings": { "DefaultConnection": "Server=(localdb)MSSQLLocalDB;Database= IdentityDB;Trusted_Connection=True;MultipleActiveResultSets=true"}}
اكيد لاحظت ان عندنا ملفين تابعة لappsettings وهم : 
  • appsettings.Development.json (يستخدم في مرحلة التطوير والاختبار)
  • appsettings.json (يستخدم مع الاصدار النهائي للتطبيق عن النشر)
  • مبدئا بتقدر تضيف نفس الكود في الملفين

  • في Connection string حددنا اسم Server وهو (localdb)MSSQLLocalDB والاسم ممكن يكون مختلف حسب الاسم في جهازك، وبعدها حددنا اسم قاعدة البيانات وهي IdentityDB واكيد بتقدر تغير الاسم بأي شيء تريده.

تم اضافة الخاصية Trusted_Connection ووضعها على "True" الي بيعني ان المشروع سيتصل بقاعدة البيانات باستخدام windows authentication  ولا توجد حاجة لتوفير اسم مستخدم وكلمة مرور قاعدة البيانات.

واضفنا كمان ;MultipleActiveResultSets=true وتختصر ب (MARS) ,هي ميزة تعمل مع SQL Server للسماح بتنفيذ مجموعات متعددة على اتصال واحد. هذا يعطي تنفيذ أسرع لعمليات.

اكيد حكينا عن هذا الموضوع سابقا في ADO.NET بتقدر ترجع للدروس للمزيد اذا كنت ترغب بذلك. 


تجهيز ملف Startup.cs 

لاستخدام Connection string اجباري ان يتم تعريف ذلك في ملف Startup.cs وحتي نعرف Connection string نضيف الكود التالي الى ملف Startup 
داخل ConfigureServices Method 

 public IConfiguration Configuration { get; }
 public Startup(IConfiguration configuration)
   {
      Configuration = configuration;
   }
تمام لاحظ ان اول الملف اضفنا constructor  يستقبل object من نوع IConfiguration  سيتم توفيره من خلال ميزة حقن التبعية Dependency Injection
services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
سطر الكود السابق يقوم بقراءة ConnectionStrings  التي تسمى DefaultConnection  من ملف appsettings واكيد الاسم حسب اختيارك بتقدر نضيف الاسم الي بناسبك. 
استخدمنا طريقة ()AddDbContext لتطبيق DB Context Class  (التي أنشأناها سابقًا) وحددنا أنها ستستخدم قاعدة بيانات SQL Server التي يتم الحصول على سلسلة الاتصال الخاصة بها من application’s configuration file ، وهو في ملف appsettings.json

اضافة ASP.NET Core Identity  داخل ملف Startup.cs 
مثل ما عرفنا  ConnectionStrings في ملف Startup اكيد لازم نعرف ASP.NET Core Identity داخل ()ConfigureServices ولتعريفها نضيف الكود التالي :
services.AddIdentity<AppUser, IdentityRole>().AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();
في هذا الكود قمنا بالتالي:
  • تحديد parameter في AddIdentity method’s مع class المستخدم لتمثيل المستخدمين (AppUser) و class المستخدم لتمثيل الأدوار Identity Role
  • في طريقة AddEntityFrameworkStores يتم تحديد أن Identity يجب أن تستخدم EF Core و DB Content class والتي هي في المشروع AppIdentityContext class 
  • تضيف طريقة AddDefaultTokenProviders موفري tokens المستخدمة لإعادة تعيين كلمات المرور وتغيير البريد الإلكتروني وتغيير عمليات أرقام الهاتف ولإنشاء two factor authentication و token generation.

واخر اضافة الى Startup class  هي إضافة ()app.UseAuthentication إلى ()Configure.

وهذا يعني أنه في كل طلب HTTP ، ستتم إضافة credentials على Cookie أو عنوان URL  سيؤدي هذا الى ربط المستخدمين الذين تقدمو بطلب HTTP إلى التطبيق.


بكون الخاص بملف Startup كامل كالتالي : 

using ASP.NET.Core.Identity.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using ASP.NET.Core.Identity.Models;
using Microsoft.AspNetCore.Identity;
namespace ASP.NET.Core.Identity
{
    public class Startup
    {
        public IConfiguration Configuration { get; }
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
            services.AddIdentity<AppUser, IdentityRole>().AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();
            services.AddControllersWithViews();
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
 انشاء Creating the Identity Database using the EF Core Migration Commands 

لإنشاء Identity Database. بنستخدم أوامر Entity Framework Core Migration.وحتي ننزل هذه الاوامر انتقل الى نافذة Package Manager Console واضف سطر الكود التالي: 
dotnet tool install --global dotnet-ef

تشغيل أوامر EF Core Migration .

حتي نشغل هذا الامر نشغل Package Manager Console وندخل الى directory  الخاص بالمشروع بتطبيق الكود :

PM> cd ASP.NET.Core.Identity
ASP.NET.Core.Identity هو اسم المشروع وبعد هيك ممكن نستعرض مكونات المشروع باستخدام الامر dir جرب وشوف النتيجة.



تمام الان حتى نعمل EF Core Migration طبق الكود التالي: 

dotnet ef migrations add MyCommand1
بتكون نتيجة التنفيذ: 


سيستغرق الأمر بضع ثوانٍ حتى يكتمل. بمجرد اكتماله سيتم انشاء مجلد باسم Migrations في المشروع يحتوي على SQL Statements اللازمة لإنشاء قاعدة البيانات في ملفات قليلة.



انشاء قاعدة البيانات 
الامر التالي يستخدم لانشاء قاعدة البيانات 
dotnet ef database update
بعد الانتهاء سيتم انشاء قاعدة البيانات للتأكد من قاعدة البيانات اذهب الى SQL Server Object Explorer
 


سيتم انشاء قاعدة بيانات باسم IdentityDB شوف الصورة :