Asp.NET Core Identity – Identity Altyapısı Kurulumu – II
Merhaba,
Bir önceki Asp.NET Core Identity – Nedir ve Temel Kavramlar? – I başlıklı içeriğimizde Asp.NET Core Identity kütüphanesine dair teorik olarak bir giriş yapmıştık. Bu içeriğimizde ise bir Asp.NET Core uygulamasında Identity alt yapısının nasıl kurulduğunu inceleyeceğiz.
Herşeyden önce Asp.NET Core Identity kütüphanesini bir projeye entegre ederken olayı hem kütüphane hem de veritabanı açısından değerlendirmemiz gerekmektedir. Kütüphane açısından Microsoft.AspNetCore.Identity kütüphanesinin projeye yüklenmiş olması gerektiğini ve Asp.NET Core uygulamalarında ilgili kütüphanenin dahili olarak geldiğini bu yüzden ekstradan işlem yapmamıza gerek kalmadığını yukarıda adresini verdiğimiz önceki makalemizde belirtmiştik.
Veritabanı açısından ise Asp.NET Core Identity kütüphanesi projeye entegre edeceği üyelik sistemiyle alakadar bir veritabanı düzeni getirmektedir. Üye bilgilerini, rolleri, tanımlamaları, token değerlerini, gerekli cross table görevi üstlenen ara tabloları vs. tüm değerleri tutacağı bir yapılanma beklemektedir. Dolayısıyla bu veritabanı karşılığını manuel bir şekilde oluşturmamız mümkün olsa dahi, fıtrat olarak Asp.NET Core Identity yapılanması en güncel ve dinamik veritabanı yaklaşımı olan Code First ile tam bir uyumluluk sergilemekte ve birazdan içeriğimizde ele alacağımız inşa neticesinde yapılan ve modellenen Identity çalışması neticesinde veritabanına uygun tabloları migrate edecek ve bizi manuel yapılanmanın getireceği olası hatalardan net bir şekilde arındırmış olacaktır.
Asp.NET Core Identity, ORM sistemi olan Entity Framework kütüphanesinin Code First yaklaşımıyla %100 uyumlu bir mimaridir.
Proje Alt Yapısı
İlk olarak “Empty” olacak şekilde bir Asp.NET Core uygulaması başlatılarak “Startup.cs” sınıfında aşağıdaki geliştirmeler yapılmalıdır.
public class Startup { public IConfiguration Configuration { get; set; } public Startup(IConfiguration configuration) => Configuration = configuration; public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); app.UseStatusCodePages(); app.UseStaticFiles(); app.UseMvc(_ => _.MapRoute("Default", "{controller=Home}/{action=Index}/{id?}")); } }
Şuanda “Startup.cs” sınıfımız olması gereken en sade şekliyle ayarlanmıştır. Birazdan Identity yapılanması inşa edilecek ve gerekli authenticaion yapılanması tekrar bu sınıf üzerinden modifiye edilecektir.
En Temel Identity Sınıfları
Asp.NET Core Identity kütüphanesinde en temel aktörlerimiz “IdentityUser” ve “IdentityRole” sınıflarıdır. En nihayetinde üyelik sistemi olan Identity mimarisi, bir kullanıcıyı genel geçer modelleyen ve o kullanıcıya dair rolleri tanımlayan bu iki sınıf ile bizlere eşlik edecektir.
Temel sınıflarımızıda tanıdıktan sonra şimdi sıra Identity mimarisini uygulamada ayağa kaldırmaya geldi…
Adım 1
Projede “Models” isimli klasör oluşturalım ve içerisine “Authentication” isminde bir klasör daha oluşturalım. Bundan sonraki tüm yapılanmalar en son oluşturulan bu “Authentication” isimli klasör içerisinde gerçekleştirilecektir.
Şimdi ilk olarak kullanıcılarımızı temsil edecek olan sınıfımızı tasarlayalım. Bu sınıfımızın adı istediğiniz herhangi bir değerde olabilir. Ben burada örnek amaçlı “AppUser” ismini veriyorum.
public class AppUser : IdentityUser { }
Görüldüğü üzere “AppUser” sınıfı oluşturulmuş ve hemen akabinde “IdentityUser” sınıfında türetilmiştir. Böylece bu sınıf uygulamada tüm kullanıcılarımıza model olabilecektir. Şimdilik bu sınıfa herhangi bir custom property girmiyorum. İlerleyen makalelerde custom property girildiği taktirde nasıl bir fark yarattığına dair mukayesede bulunacağız…
Adım 2
Bu içeriğimizdeki esas gayemiz basit bir Identity mekanizmasını ayağa kaldırabilmektir. Bundan dolayı kullanıcıları temsil eden bir sınıfın olması bizim için yeterlidir lakin yukarıda bahsedilen IdentityRole sınıfından türeyen ve sistemdeki rolleri tanımlayan bir sınıf inşa etmemize şimdilik gerek yoktur. Merak etmeyin, ilerleyen makalelerde a’dan z’ye herşeyi, en doğru şekilde incelemiş olacaksınız 🙂
Artık bu noktaya kadar elimizde kullanıcıları modelleyen bir “AppUser” sınıfı mevcuttur. Dolayısıyla şimdi yapmamız gereken Code First yaklaşımıyla üretilecek/migrate edilecek olan veritabanımızın bir karşılığı olan DbContext sınıfını üretmektir. Bunun için “Models” klasörü altında “Context” isimli bir klasör oluşturalım ve içerisinde “AppDbContext” isminde bir sınıf üretelim.
public class AppDbContext : IdentityDbContext<AppUser> { public AppDbContext(DbContextOptions<AppDbContext> dbContext) : base(dbContext) { } }
Yukarıdaki kod bloğunu incelerseniz eğer oluşturulan context sınıfı normalde “DbContext” sınıfından türetilmesi gerekiyordu. Lakin biz sistemimizde Identity kullandığımızdan dolayı bu identity yapısının karşılığını veritabanında oluşturtmamız gerekmektedir ve bunu “IdentityDbContext” sınıfı ile gerçekleştirebilmekteyiz. Dolayısıyla context sınıfının hangi identity ile birlikte çalışacağını belirtebilmek için “IdentityDbContext” sınıfından türetilmektedir. Ve dikkat edilirse generic olarak bu identity yapılanmasının tarafımızca oluşturulan “AppUser” isimli sınıf ile gerçekleştirildiğini belirtmiş oluyoruz.
Context sınıfını inşa ettikten sonra migrate işlemi neticesinde hedef sunucu providerını “appsettings.json” dosyasında aşağıdaki şekilde belirleyelim;
{ "ConnectionStrings": { "SqlServerConnectionString": "Server=.;Database=IdentityExampleDb;Trusted_Connection=True;" }, "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*" }
Adım 3
Artık uygulamada inşa edilen bu identity yapılanması “Startup.cs” sınıfı üzerinden uygulamaya dahil edilmelidir. Bunun için aşağıdaki çalışma yeterlidir…
public class Startup { public IConfiguration Configuration { get; set; } public Startup(IConfiguration configuration) => Configuration = configuration; public void ConfigureServices(IServiceCollection services) { services.AddDbContext<AppDbContext>(_ => _.UseSqlServer(Configuration["ConnectionStrings:SqlServerConnectionString"])); services.AddIdentity<AppUser, IdentityRole>().AddEntityFrameworkStores<AppDbContext>(); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); app.UseStatusCodePages(); app.UseStaticFiles(); app.UseAuthentication(); app.UseMvc(_ => _.MapRoute("Default", "{controller=Home}/{action=Index}/{id?}")); } }
7. satır‘da görüldüğü üzere uygulamaya geliştirdiğimiz context nesnesi DbContext olarak tanıtılmaktadır.
8. satır‘da görüldüğü üzere ise uygulamaya identity yapılanmasına dair gerekli entegrasyonu “AddIdentity” metodu ile gerçekleştirmekteyiz. Dikkat ederseniz generic olarak birinci parametreye bu identity yapılanmasının kullanacağı IdentityUser yapılanmasını istemektedir. Bunun için tarafımızdan “AppUser” sınıfı verilmiştir. Lakin ikinci parametreye ise tarafımızca herhangi bir IdentityRole sınıfından türeyen sınıf inşa edilmediğinden dolayı direkt olarak “IdentityRole” sınıfı verilmiştir. Yani anlayacağınız temelde biz sadece IdentityUser sınıfından türeyen “AppUser” sınıfını inşa ederek en temel üyelik yönetimi yapılanmasını gerçekleştirmiş bulunmaktayız. Buradaki işlem neticesinde “AddEntityFrameworkStores” generic metodu sayesinde “AppDbContext” isminde oluşturduğumuz contexte özel depolama gerçekleştirmiş bulunmaktayız.
Ayrıca 19. satır‘da “UseAuthentication” metodu sayesinde uygulamanın identity ile kimlik doğrulaması gerçekleştireceğini belirtmiş bulunmaktayız.
Evet…
Bu işlemler neticesinde artık uygulamamızda bir Identity altyapısı mevcut hale getirilmiştir. Şimdi Code First yaklaşımı ile migrationları oluşturup veritabanımızı sunucuya migrate edelim. Asp.NET Core uygulamalarında migration işlemlerini tam teferruatlı inceleyebilmek için Asp.NET Core 2 MVC’de Migrations İle Veritabanı İşlemleri başlıklı makaleye göz atabilirsiniz.
dotnet ef migrations add mig_1 dotnet ef database update
Bu işlem neticesinde migrate edilen veritabanı ve oluşturulan tabloları aşağıdaki görselde olduğu gibidir;
Netice olarak; bu içeriğimizde sadece üyeleri temsil edecek olan sınıfı inşa ederek IdentityDbContext nesnesi oluşturmayı, Startup sınıfına Identity mimarisini entegre ederek projeye tüm bu yapılanmayla ayağa kaldırmayı incelemiş olduk. Yani uzun lafın kısası bir projede en sade haliyle Identity mimarisinin nasıl kurulduğunu görmüş olduk.
Sonraki makalemizde ise neticede oluşturulan veritabanında Identity mimarisine özel tabloları inceleyeceğiz. O halde şimdilik görüşmek üzere…
İlgilenenlerin faydalanması dileğiyle…
İyi çalışmalar…
Not : Örnek projeyi indirmek için buraya tıklayınız.
Merhaba hocam makaleniz için çok teşekkür ederim bu konuyla ilgili bir soru soracaktım Asp .net Core Identity mimarisini bir tek MVC de mi kullanabiliyoruz ? Web Api ile bu mimariyi kullanabiliyor muyuz? Kullanabiliyorsak aynı yapılandırmalar Web Api içinde geçerli mi?
Merhaba,
Cookie bazlı yetkilendirme haricinde diğer işlemler geçerlidir. Fakat bizler genellikle Web API’lar da token bazlı yetkilendirme yapmayı tercih ediyoruz. İlgili konuya dair yakın zamanda yazı dizisinin devamı niteliğinde bir makale yayınlayacağım. Beklemeksizin konuya dair bilgi edinmek için https://www.gencayyildiz.com/blog/asp-net-core-angular-7-web-api-token-authentication-kullanimi/ adresindeki makaleye göz atabilirsiniz.
Uygulamayı Asp.Net Core 3.1 ile oluşturabilmek için ne yapmamız gerekiyor.
Uygulamayı 3.1 ile oluşturabilmek için Visual Studio’da .NET Core 3.1 seçili bir web uygulaması oluşturmanız gerekiyor.
Evet öyle yaptım ama siz projenizde AspNetCore.App 2.2.0 paketini kullanmışsınız. Bu paket Net Core 3.1 de oluşturduğum projeye eklediğimde paket üzerinde sarı üçgen bir uyarı oluşuyor ve AppDBContext de IdentityDbContext context inden inherit edemiyorum. Ama projeyi .Net Core 2.2 ye dönüştürdüğümde hiç sıkıntısız çalışıyor. Acaba başka bir kütüphanemi kullanmam lazım.
3.1 versiyon ile de bu makalede yazılanları ele alabilirsiniz. Ekstradan düşük versiyonlara geçiş yapılmasına gerek yok.
Merhaba, yukarıda Fisun Hanım’da size sormuş fakat aynı sorunu bende yaşıyorum. Core 3.1 ‘ de sizin bahsettiğiniz adımları takip ettiğim zaman AppContex’te DbContext option’a AppContext’i verdiğimde entityframeworkcore için context tipi uyumlu değil hatası alıyorum.
Muhtemelen ya uygulamaniz 3.1 değil ya da kullandığınız Entity Framework Core kütüphaneniz. Nuget’ten ilgili kütüphaneyi kontrol edebilir misiniz?
Nuget paket olarak aşağıdakini yüklerseniz sorun çözümleniyor.
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Elinize sağlık şöyle bir not düşmek istiyorum.
.net core 3.0 ve sonraki sürümlerde startup dosyasına
app.UseAuthentication();
app.UseAuthorization();
bu sıra ile yazmak gerekiyor
Teşekkürler… 🙂
Şöyle bir sorum vardı hocam. Giriş yapan kullanıcının yetkisi bulunduğu sayfalarda giriş bilgilerinin veri tabanı sorgusu yapılarak o kullanıcıya ait bilgileri nasıl kullanabiliriz?
Direkt olarak ‘User’ property’si size kullanıcıya dair bilgileri getirecektir. O bilgiler üzerinden ‘UserManager’ ile aşağıdaki sorgulamayı yapabilirsiniz.
Serimizin ileriki makalelerinde ilgili konuya değinildiğini ve detaylı bir şekilde sindirerek okumanızı öneririm.
Kolay gelsin…
Merhaba bi sorum olacaktı umarım en kısa sürede görürsünüz.
Uygulamada iki tip kullanıcı olacaktır. (Yönetici, Kullanıcı) Yönetici tanımı manuel oluşturulabilir, ancak uygulama girişi tek olacaktır.
Kullanıcı kayıt işlemi.(Register) (e-posta, şifre, ad soyad ve cep telefonu – validasyonlar yapılacaktır)
Yönetici ve Kullanıcı için giriş işlemi. (Login)
Uygulama menüsü yönetici için ve kullanıcı için farklılık gösterecektir.
bu işlemler için nasıl bi yol izlemem gerekiyor. Identity ve rol yetkilendrme mi kullanacagım?
Evet, identity mimarisini kullanabilir, rol tabanlı yetkilendirme yapabilirsiniz.
Öncelikle cevabınız için çok teşekkür ederim. Peki nasıl başlamam gerekiyor bu işleme. Ben yöneticiyi manuel oluşturmayıp kayıt işlemi yapayım diyorum. Yani hem kullanıcı için hem de yönetici icin hem login hem de kayıt yaptırıcam fakat rol kısmını burda nasıl kulanıcam?
Yada sizce nasıl bi yol izlemeliyim?
Bu yazı serisinde, bu işin nasıl yapıldığını detaylıca anlatmaya çalıştığım. Dolayısıyla size bu seriyi uygulayarak okumanızı tavsiye ediyorum.
Emeğinize sağlık. Çok teşekkürler.
Öncelikle bu serideki makalelerinizin tamamını okudum. Hepsi de çok özenle hazırlanmış, çok teşekkür ederim.
Ancak sizlere bir sorum olacak. Şu an bir MVC projesi hazırlamaya başladım. Projedeki veritabanım AppDb adında ve AppDbContext nesnesini kullanıyor. IdentityDbContext nesnesiyle oluşturacağım kullanıcılar için de aynı veritabanını kullanabilir miyim? Yoksa farklı bir veritabanı mı oluşturmam gerekiyor.
Bir de uygulamayı ve kullanıcıları aynı veritabanında tutmak mı daha verimli ve kullanışlı olur, farklı veritabanlarında tutmak mı?
İlginiz için şimdiden teşekkür ederim.
Merhaba,
1. Aynı veritabanını kullanabilirsiniz.
2. Bu konuya dair yorum yapabilmek için projenin kapsamı doğrultusunda değerlendirme yapılması daha doğru olacaktır.
Sevgilerimle…
Merhaba, makale çok güzel elinize sağlık. Sormak istediğim soru şu;
Biz yazdığınız gibi entitylerimiz için DbContext sınıfı türetiyoruz ve bütün entitylerimizi oraya belirtiyoruz. Burada ise IdentityDbContext tanımlıyoruz. Bunları birleştirme şansımız var mı? Doğrusu nasıldır.
Yoksa User roller vs. için IdentityDbContext ayrı mı tutulmalıdır bu mu doğrusudur?
Tam sorabildim mi bilmiyorum ama umarım anlatabildim.
Teşekkürler
Canım hocam, bal hocam, vaktiniz olursa bu makaleleri EntityFramework 7.0 için de günceller misiniz
Teşekkürler bal hocam, can hocam.
👍
Makale için teşekkürler. Emeğine sağlık