Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET Core Identity – Kullanıcı Validasyon Ayarları ve IUserValidator Arayüzü – VII

Merhaba,

Bir önceki Şifre Validasyon Ayarları ve IPasswordValidator Arayüzü başlıklı makalemizde Identity mimarisinde varsayılan ayarları bulunan kullanıcı şifresi üzerinde validasyon ayarlarını değiştirmeyi ve özelleştirilmiş validasyon yapılanmasının nasıl inşa edildiğini ele almıştık. Bu içeriğimizde ise yine aynı mantıkta direkt kullanıcıya dair varsayılan validasyon ayarlarını inceleyeceğiz ve benzer şekilde özelleştirilmiş doğrulama yapılanmasının IUserValidator arayüzü ile nasıl geliştirildiğini ele alacağız.

Şimdi…

Yazı dizimiz boyunca geliştirdiğimiz örnek projemizin en son halini ele alalım ve aşağıdaki gibi bir kullanıcı kaydı gerçekleştirmeye çalışalım.
Asp.NET Core Identity - Kullanıcı Validasyon Ayarları ve IUserValidator Arayüzü – VII
Dikkat ederseniz “Gençay” username değerine sahip kullanıcıyı oluşturmaya çalışırken kullanıcı adının sadece harf ve sayılardan oluşabileceğini söyleyen ve bunda dolayı geçersiz olduğuna dair mesaj veren bir validasyona yakalandık.

Neden mi?
Çünkü Identity mekanizmasında kullanıcıya dair default gelen validasyonlar mevcuttur. Bu validasyonlardan “AllowedUserNameCharacters” kullanıcı adına özel hangi karakterleri barındırabileceğini tutmakta ve kullanıcı adı değeri havuzda eşleşmeyen herhangi bir karakter barındırıyorsa yukarıdaki hatayı fırlatmaktadır.

Bir başka durumu incelemek için önceden kaydedilen tüm kullanıcılarımızı aşağıdaki gibi listeleyelim(/User/Index)
Asp.NET Core Identity - Kullanıcı Validasyon Ayarları ve IUserValidator Arayüzü – VII
Dikkat ederseniz birden fazla kullanıcı benzer email adreslerini kullanabilmektedir. Evet, her ne kadar bir uygulamada email adresinin mükerrer olması istenmesede Identity mimarisinde bu ayar tarafımızın kararına bırakılmıştır ve varsayılan olarak email tekil olmayacak şekilde ayarlanmıştır.

İşte burada olduğu gibi email adresinin tekil olup olmadığına dair konfigürasyonuda “RequireUniqueEmail” propertysi tutmaktadır.

Birazdan bu default validasyonlara nasıl müdahale edildiğine dair incelemede bulunacağız lakin o satırlara gelmeden mühim bir noktaya temas etmek istiyorum…

Identity mekanizmasında UserName alanı değiştirilemez bir şekilde default olarak unique(tekil)tir.

Evet… Buradan da anlaşılan o ki, Identity mekanizmasında tüm varsayımsal ayarlar opsiyonel olarak değiştirilebilir değildir.

Varsayılan User Validasyon Ayarlarını Değiştirme

Yukarıda detaylıca ele aldığımız her iki default validation yapılanmasına müdahalede bulunabilmek için “Startup.cs” sınıfı içerisindeki “ConfigureServices” metodunda aşağıdaki gibi çalışma yapmamız 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, AppRole>(_ =>
            {
                _.Password.RequiredLength = 5; //En az kaç karakterli olması gerektiğini belirtiyoruz.
                _.Password.RequireNonAlphanumeric = false; //Alfanumerik zorunluluğunu kaldırıyoruz.
                _.Password.RequireLowercase = false; //Küçük harf zorunluluğunu kaldırıyoruz.
                _.Password.RequireUppercase = false; //Büyük harf zorunluluğunu kaldırıyoruz.
                _.Password.RequireDigit = false; //0-9 arası sayısal karakter zorunluluğunu kaldırıyoruz.

                _.User.RequireUniqueEmail = true; //Email adreslerini tekilleştiriyoruz.
                _.User.AllowedUserNameCharacters = "abcçdefghiıjklmnoöpqrsştuüvwxyzABCÇDEFGHIİJKLMNOÖPQRSŞTUÜVWXYZ0123456789-._@+"; //Kullanıcı adında geçerli olan karakterleri belirtiyoruz.
            }).AddPasswordValidator<CustomPasswordValidation>().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?}"));
        }
    }

Yukarıdaki kod bloğunda, uygulamaya Identity mekanizmasını dahil eden “AddIdentity” metodu içerisinde 16 ve 17. satırlara göz atarsanız eğer default ayarlar değiştirilmiştir. Burada “AllowedUserNameCharacters” özelliğine tekrar dikkatinizi çekmek istiyorum. Bu özelliğin varsayılan değerini yani kullanıcı adının barındırabileceği varsayılan karakterleri görmek istiyorsanız eğer şuradaki adrese göz atmanız yeterlidir. İlgili adreste varsayılan karakter değerlerine göz atarsanız içerisinde Türkçe karakterlerin olmadığını göreceksiniz. Bizler yukarıda bu değerlere ekstradan örneklendirme mahiyetinde Türkçe karakterleride eklemiş bulunmaktayız.

Bu işlemlerden sonra artık uygulamamızda varsayılan validasyon durumlarından ziyade bizim ayarladığımız şekilde bir doğrulama kontrolü söz konusu olacaktır. Peki bunların dışında başka validasyonlar ayarlayabilir miyiz? sorusunun cevabını ise “IUserValidator” arayüzü ile özelleştirilmiş validasyonlar verecektir.

IUserValidator Arayüzü İle Özel Validasyon Geliştirme

IUserValidator, kullanıcıya dair istediğimiz hertürlü doğrulama kontrolü yapmamızı sağlayan bir arayüzdür. İlgili arayüzü şöyle bir incelersek eğer;
Asp.NET Core Identity - Kullanıcı Validasyon Ayarları ve IUserValidator Arayüzü – VII
görüldüğü üzere kullanıcı yönetimini sağlayan UserManager nesnesiyle birlikte bilgileri girilen kullanıcı nesnesi parametre olarak elde edilebilmektedir.

IUserValidator arayüzünü kullanarak özelleştirilmiş validasyon yapılanması inşa edebilmek için önceki makalemizde uygulamanın ana dizininde oluşturduğumuz “CustomValidations” klasörü içerisine “CustomUserValidation” isminde bir sınıf ekleyelim ve içeriğini aşağıdaki gibi geliştirelim.

    public class CustomUserValidation : IUserValidator<AppUser>
    {
        public Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user)
        {
            List<IdentityError> errors = new List<IdentityError>();

            if (int.TryParse(user.UserName[0].ToString(), out int _)) //Kullanıcı adının sayısal ifadeyle başlamaması kontrolü
                errors.Add(new IdentityError { Code = "UserNameNumberStartWith", Description = "Kullanıcı adı sayısal ifadeyle başlayamaz..." });
            if (user.UserName.Length < 3 && user.UserName.Length > 25) //Kullanıcı adının 3 ile 25 karakter arasında olması
                errors.Add(new IdentityError { Code = "UserNameLenhth", Description = "Kullanıcı adı 3 - 15 karakter arasında olmalıdır..." });
            if (user.Email.Length > 70) // Emailin 70 karakterden fazla olmaması kontrolü
                errors.Add(new IdentityError { Code = "EmailLenhth", Description = "Email 70 karakterden fazla olamaz..." });

            if (!errors.Any())
                return Task.FromResult(IdentityResult.Success);
            return Task.FromResult(IdentityResult.Failed(errors.ToArray()));
        }
    }

Yukarıda geliştirdiğimiz validasyonu incelerseniz eğer kullanıcı adının baş harfinin sayısal değerlerle başlamamasında tutun emailin karakter uzunluğuna kadar belli başlı doğrulama algoritmaları gerçekleştirilmiştir.

Geliştirme işleminin neticesinde artık ilgili validasyonu Identity mekanizmasına entegre etmemiz gerekmektedir. Bunun için tekrar “Startup.cs” dosyasına giderek;

    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, AppRole>(_ =>
            {
                _.Password.RequiredLength = 5; //En az kaç karakterli olması gerektiğini belirtiyoruz.
                _.Password.RequireNonAlphanumeric = false; //Alfanumerik zorunluluğunu kaldırıyoruz.
                _.Password.RequireLowercase = false; //Küçük harf zorunluluğunu kaldırıyoruz.
                _.Password.RequireUppercase = false; //Büyük harf zorunluluğunu kaldırıyoruz.
                _.Password.RequireDigit = false; //0-9 arası sayısal karakter zorunluluğunu kaldırıyoruz.

                _.User.RequireUniqueEmail = true; //Email adreslerini tekilleştiriyoruz.
                _.User.AllowedUserNameCharacters = "abcçdefghiıjklmnoöpqrsştuüvwxyzABCÇDEFGHIİJKLMNOÖPQRSŞTUÜVWXYZ0123456789-._@+"; //Kullanıcı adında geçerli olan karakterleri belirtiyoruz.
            }).AddPasswordValidator<CustomPasswordValidation>()
              .AddUserValidator<CustomUserValidation>().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?}"));
        }
    }

“ConfigureServices” metodu içerisinde 19. satırda olduğu gibi “AddUserValidator” generic metodunu eklememiz yeterlidir.

Böylece uygulamamızda artık hem password hemde user temelli custom validasyon yapılanması sağlanmış bulunmaktadır.

Bir sonraki içeriğimizde varsayılan olarak gelen doğrulama mesajlarının nasıl özelleştirileceği üzerine olacaktır. O halde şimdilik görüşmek üzere diyelim…

İlgilenenlerin faydalanması dileğiyle…
İyi çalışmalar…

Not : Örnek projeyi indirmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

6 Cevaplar

  1. osman dedi ki:

    İyi günler hocam;
    username zorunluluğunu devre dışı bırakabilir miyim? Benzersiz kayıt olarak sadece e-posta adresini kullanmak istiyorum. Nasıl yapmalıyım?

    • Gençay dedi ki:

      Username zorunluluğunu devre dışı bırakmak direkt olarak mümkün değildir. Lakin email için alınan değerin backend’de direkt olarak username değerine basılması uygun bir çözüm olacaktır…

      Farazi olarak;

       AppUser appUser = new AppUser
                  {
                      UserName = appUserViewModel.Email,
                      Email = appUserViewModel.Email
                  };
      await _userManager.CreateAsync(appUser, appUserViewModel.Sifre);
      
  2. Baran dedi ki:

    Merhabalar, Identitynin fırlattığı exceptionları Türkçe olarka göstermek mümkün mü?

  3. Abdullah Halit Korucuoğlu dedi ki:

    Multi Tenant bir uygulama için Username zorunluluğunu kaldırmam gerekiyor. Bunu yapmak imkansız mı?

  1. 16 Ağustos 2019

    […] Asp.NET Core Identity – Kullanıcı Validasyon Ayarları ve IUserValidator Arayüzü – VII […]

Bir cevap yazın

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