Asp.Net Core 3.1 Custom Authentication & Authorization – Real World Application – Part1 Asp.Net Core 3.1 Entity Framework Core Code First Implementation

Selamlar ,

Bu makalede Asp.Net Core 3.1 ile Microsoft Identity altyapısını kullanmadan , tamamen kendi metodlarımız ve veri tabanı yapımızla custom şekilde bir Authentication & Authorization WebApi’yı yapacağız.

Bu projeyi orta ölçekli bir gerçek dünya uygulaması olarak geliştirmeyi planlıyorum. Bu yazı A&A projesi için giriş olacaktır. Uygulama bittiğinde bu konu hakkında 8 makale olmasını planlıyorum.(Bu sayı değişebilir.)

Projede kullanacağımız teknoloji ve patternler ;

  • Entity Framework Core Code First (SQL Server)
  • Repository & Unit Of Work Pattern
  • JWT (JSON Web Tokens), IETF kuruluşu tarafından tasarlanan standart bir token biçimidir (Bkz. RFC 7519).
  • Redis Cache ( Cache işlemleri için )
  • Elastic Search ( Loglama işlemleri için )
  • Kibana ( Elastic Monitor )
  • Asp.Net Core Dependency Injection
  • Asp.Net Core Middleware

1- Alt Yapı Oluşturulması ve Entity Framework Core Code First (SQL Server)

Proje dosya yapım ve klasör görünümüm aşağıda ki gibidir

  • Docs – Projemize ait dosyların yer alacağı klasör,
  • Source – Kodlarımızın yer aldığı klasör
    • Core – Application , Common , Domain kodlarımızın yer aldığı klasör
      • Application – Uygulama servislerimizin , Interfacelerin , logic kodların yer aldığı katman
      • Common – Projenin genelinde kullanacağımız ortak classlar , kod blokları enumlar vs.
      • Domain – Entitylerimiz , Value Objectlerimiz , Enumlarımız ve domaine özgü logiclerimiz.
    • Presentation
      • WebApi – Yaptığımız projenin sunum katmanı.
    • Infrastructure
      • Infrastructure -Dependency Ayarlarımız , Dosya okuma/Yazma , bildirim işlemleri , entegrasyon işlemi gibi kodlamaların yapıldığı katman
      • Persistence – Projenin sürdürülebilirliğinin kodlandığı kısımdır. Biz burada DbContext , Migrations ,Configurations, Seeding işlemlerini yapacağız.
  • Test – Test projelerinin yer aldığı klasör.

Entity Framework Code First İmplementasyonu

Oluşturacağımız entitylerimiz için Common projesi altına bir BaseEntity sınıfı oluşturalım ( tüm entitylerde ki ortak özellikler tanımlanır) Ve bu entity de kullandığımız StatusType enumunu oluşturalım.

public class BaseEntity
    {
        public virtual long Id { get; protected set; }
        public virtual StatusType Status { get; set; }

        public BaseEntity()
        {
            this.Status = StatusType.Available;
        }
    }


public enum StatusType
    {
        Passive = 0,
        Available = 1
    }

Auditlerin tutulmasını istediğimiz entityler ve Softdelete olmasını istediğimiz entitylerimiz için 2 adet interface oluşturalım; IAudit ISoftDelete

public interface IAudit
    {
        long CreatorUserId { get; }
        DateTime? LastModTime { get; }
        long? ModifierUserId { get; }
        DateTime CreationTime { get; }
    }

 public interface ISoftDeleted
    {
        bool IsDeleted { get; }
    }

Domain Projesi altına Entity Klasörü oluşturup ardından User.cs adında ilk entitymizi oluşturalım ;

public class User : BaseEntity, ISoftDeleted, IAudit
    {
        public virtual string UserName { get; protected set; }
        public virtual string Name { get; protected set; }
        public virtual string SurName { get; protected set; }
        public virtual string Email { get; protected set; }
        public string Password { get; protected set; }
        public virtual string PasswordSalt { get; protected set; }
        public virtual long CreatorUserId { get; protected set; }
        public virtual long? ModifierUserId { get; protected set; }
        public virtual DateTime CreationTime { get; protected set; }
        public virtual DateTime? LastModTime { get; protected set; }
        public virtual bool IsDeleted { get; protected set; }

        public User() { }

        public User(string _userName, string _name, string _surName ,string _email, string _password, string _passwordSalt)
        {
            this.UserName = _userName;
            this.Name = _name;
            this.SurName = _surName;
            this.Email = _email;
            this.PasswordSalt = _passwordSalt;
            this.Password = _password;
            this.CreatorUserId = 1;
            this.CreationTime = DateTime.Now;
            this.IsDeleted = false;
            this.Status = StatusType.Available;
        }
    }

Dikkat ederseniz ID kolonu yok , ID kolonu BaseEntity sınıfından gelmekte. Ayrıca user entitymiz Softdelete ve Audit interfacelerine sahip.

Persistence Projesine , Context Klasörü eklenir. Aşağıda ki gibi context tanımları yapılır

public class AuthenticationContext : DbContext
    {
        public AuthenticationContext(DbContextOptions<AuthenticationContext> options)
          : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.ApplyConfigurationsFromAssembly(typeof(UserEntityConfig).Assembly);
        }

        public DbSet<User> User { get; set; }
    }

Ardından WebApi projemizde bu contexti install etmek için bir yapı kuralım. Burada direk startup.cs in altında contexti tanımlamak yerine daha temiz ve ayrı bir şekilde işlemlerimi yapmak için IInstaller adında bir Interface oluşturup daha sonra bu interfaceden türeyen installerları startupda ayağa kaldıracak bir InstallerExtensions sınıfı yazıyorum.

public interface IInstaller
    {
        void InstallServices(IServiceCollection services, IConfiguration configuration);
    }

 public class DbInstaller : IInstaller
    {
        public void InstallServices(IServiceCollection services, IConfiguration configuration)
        {
            IServiceCollection serviceCollection = services.AddDbContext<AuthenticationContext>(options => options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
            
        }
    }

 public static class InstallerExtensions
    {
        public static void InstallServicesInAssembly(this IServiceCollection services, IConfiguration configuration)
        {
            var installers = typeof(Startup).Assembly.ExportedTypes.Where(x =>
                typeof(IInstaller).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract).Select(Activator.CreateInstance).Cast<IInstaller>().ToList();

            installers.ForEach(installer => installer.InstallServices(services, configuration));
        }
    }
DI & Installer

En son olarak appsettings.json da connection parametrelerini yazıp ardından migration ekleyip veritabanımızı update ediyor ve EntityFramework Core Code First ü projemize dahil etmiş oluyoruz.

appsettings.json

"ConnectionStrings": {
    "DefaultConnection": "Server=.\\SQLEXPRESS;Database=Authentication;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

Startup Project olarak WebApi projemizi seçiyor ardından Manager Console dan Sırasıyla

  • Enable-Migrations
  • Add-Migrations Initial
  • Update-Database

Komutlarını çalıştırarak ilk makalemizin sonuna geliyoruz.

Proje Git Reposu : https://github.com/aburakbasaran/Authentication

Görüşmek Üzere 🙂

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Post comment