26 Kasım 2018 Pazartesi

Mvc'de Filtrleme İşlemleri - Attribute Kullanımı - AOP

    S.a. Arkadaşlar,
    Bugünkü yazımız üye yetki kontrolü ile ilgili olacaktır. Bir sisteminiz var ve bu burada bulunan sayfalara herkes giriş yaptığında girebilecek mi, yoksa bazı sayfalara sadece belirlediğiniz kullanıcı tipleri mi erişebilecektir. Eğer böyle bir sisteminiz varsa doğru yere geldiniz. Burada her metodu ayrı ayrı kod yazıp kontrol etmeyeceğiz. Burada devreye attribute'leri devreye sokacağız.

    Bu konu üzerinde aslında biraz kafa yordum. Birden fazla yöntem mevcut olabilir. Ama biz burada rol tanımlama ile problemimizi çözdük. Belki de bunun için biraz daha araştırma yaptığım için daha sempatik gelmiş olabilir. Konuya geçmeden önce şunu da söylemek isterim. Bu konuyla ilgili AOP kavramına da göz atmanızı tavsiye ederim. Ben bu çözümü ürettikten sonra AOP kavramını okudum ve ne kadar isabetli bir iş yaptığımı görünce ayrıca mutlu oldum.

    Burada okuyup da aklımda kalan en iyi kavram herhalde "precondition"'dir. Çünkü metot ve sınıfınıza girmeden önce yukarıdaki koşulları kontrol ediyor ve eğer belirttiğiniz koşullardan geçmiyorsa metot veya sınıfınıza girmeyecektir. O yüzden en basit ve anlamlı hali olarak bu aklımda kaldı. Bu konuda güzel Türkçe içerikler de mevcuttur. Biz artık kodumuza dönelim

     Ben öncelikle bunun için enum tanımladım ve bu enum üzerinden ilerleyeceğim. Siz bunu farklı şekillerde de çözebilirsiniz. Pek değişmeyecek bir yapı olduğu için enum olarak tanımlamam benim için en avantajlı olacak diye düşündüm. Tanımlamam şu şekildedir:

public enum RoleNames
{
     Admin = 1,
     Editor = 2,
     Teacher = 3,
     Student = 4
}
 
      Şimdi sınıfımızı AuthorizeAttribute'ten türetmemiz lazım. Daha sonra metodumuzu ezeceğiz ve kendi istediğimiz şekle getireceğiz. Burada eğer belirlenen koşulları sağlıyorsa işleme devam edebilecek, aksi halde belirttiğimiz sınıfa yönlendirecektir. Şimdi geri kalan kodumuzu verelim.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
class AuthorizeRoleAttribute : AuthorizeAttribute
    {
        private RoleNames[] roleNames { get; set; }

        public AuthorizeRoleAttribute(params RoleNames[] roles)
        {
            roleNames = roles;
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            foreach (var role in roleNames)
            {
                if (HttpContext.Current.Session["MemberAuth"].GetInt() == role.GetInt())
                {
                    return;
                }
            }

            filterContext.Result = new RedirectResult("Hata Sayfasi");
        }
    }

      Burada metod ve class diye belirttiğimiz attributeler class veya metod ile çalışabileceğini belirttik. Yapılandırıcı metodumuz içinde enum tanımlıyoruz. Daha sonra metodu ezerek kendi kodumuzu yazıyoruz. Ben kullanıcı giriş yaptığında verileri session'da tuttuğum için session'daki kullanıcı tipi , tanımlanan tipler arasında mevcut mu kontrolü yapıyorum. Eğer varsa, return deyip işlemimize devam ediyoruz. Aksiye halde hata sayfasına yönlendiriyoruz.

       Not: GetInt() benim ektension metodumdur. Sizde hata vermemesi için int.Parse(role.ToString()) yapısını kullanabilir veya siz de extension metod tanımlayabilirsiniz. İlk defa bu tanımı duyuyorsanız araştırmanızı öneririm.
 
      Şimdi controller tarafında oluşturduğumuz attribute kullanalım.

[AuthorizeRoleAttribute(RoleNames.Admin, RoleNames.Editor)]
public ActionResult HerHangiBirSayfa()
{
      return View();
}

     Yazının sonuna doğru ilerlerken hadi yazdığımız kodu yürütelim. Sayfamıza tıklamadan önce giriş yapmış olmak gerekirdi. Bunu burada görmüyoruz çünkü onu üst sınıfa tanımlamıştım. Giriş yapınca session'ı da doldurmuş oluyoruz. Bu kullanıcımız admin veya editör ise bu sayfaya girebilecektir. Öğrenci veya öğretmen ise redirect ile istediğiniz sayfaya yönlenecektir.

    Not: Tüm controller'im bir üst sınıftan üretiliyor. O yüzden genel yetki girişini üst sınıfın üzerinde tanımladım ve bu şekilde tüm metot ve sınıflarda bu işlemi yapmaktan kurtuldum. Tasarımınızı yaparken buna dikkat ederseniz çok rahat edeceksiniz. Bir değişiklik yapmanız gerektiğinde sadece base (üst) sınıfınızda yapmanız yeterli olacaktır.

    Okunabilir kodlar yazmak dileğiyle. Hoşça kalın.

Hiç yorum yok:

Yorum Gönder