Makale Özeti

Bir önceki ASP.NET 2.0 Güvenlik adlı makalemizde güvenlik kavramından bahsedip Windows Tabanlı Güvnelik kavramını açıklamıştık. Bu makalemizde Form Tabanlı Güvenlik kavramından bahsediyor olacağız...

Makale

Bir önceki makalemizde ASP.NET 2.0'daki güvenlik kavramına giriş yapıp temel terimlerden bahsettikten sonra Windows Tabanlı Güvenlik'i açıklamıştık. Şimdi sıra geldi Form Tabanlı Güvenlik'ten bahsetmeye. Eğer bir önceki makaleyi okuduysanız Windows Tabanlı Güvenlik'in intranet uygulamaları için uygun bir çözüm olacağını hatırlıyorsunuzdur. Internet uygulamaları için ise uygun çözümün Form Tabanlı Güvenlik olduğundan da bir önceki makalede bahsetmiştik. Windows Tabanlı Güvenlik'te her kullanıcı için domainde veya uygulamanın çalışacak olduğu makinede Windows'ta bir kullanıcı oluşturmak gerekiyor ama binlerce kişinin erişeceği bir sistemde bu kişileri teker teker Windows'ta oluşturmak pek de mantıklı bir çözüm değildir. Form Tabanlı Güvenlik'te kullanıcıları uygulama bazında oluşturup gerekli kimlik denetimini uygulama bazındaki bilgilere göre gerçekleştiriyoruz veya kullanıcıları herhangi bir veri tabanı sisteminde saklayıp kimlik denetimini ilgili veri tabanından da gerçekleştirebiliriz. Sözü daha fazla uzatmadan Form Tabanlı Güvenlik'i açıklamaya başlayalım.

Uygulamamızda Form Tabanlı Güvenlik kullanmak için konfigürasyon dosyasında (web.config) gerekli ayarları yapmak gerekiyor.

<authentication mode="Forms">

<forms loginUrl="login.aspx" name="AspNetGuvenlikDemo" defaultUrl="default.aspx" />

</authentication>

Yukarıdaki kod bloğuna baktığımızda  gözümüze ilk çarpan şey authentication mode'un Forms olarak ayarlandığı olmaktadır, bu söz dizimi ile sitenin güvenlik modunun Form Tabanlı Güvenlik olduğunu bildiriyoruz. Hemen alttaki satırda ise Form Tabanlı Güvenlik'in özel ayarlarını yapıyoruz, loginUrl ile kimlik denetimi gereken bir yere erişilmeye çalışıldığında kullanıcının otomatik olarak kullanıcı adı ve parola girmesi gereken yönlendirilecek olan sayfanın yolu belirtiliyor, name alanında ise kullanıcın sistemine atılacak olan Cookie'nin adı belirtiliyor, defaultUrl ile de kullanıcı direkt login sayfasına girdiğinde geçerli kullanıcı adı ve şifreyi belirttikten sonra varsayılan olarak yönlendirileceği sayfanın yolu belirtiliyor. Şimdi  forms alanındaki diğer ayarları bir tablo halinde açıklayalım.

protection Kullanıcının sistemine atılacak olan Cookie'nin korunma modu belirtiliyor. Burada mümkün olan toplam dört tane seçenek vardır. Bunlar:
All: Cookie hem data doğrulama hem de şifreleme algoritmaları ile korunur. Varsayılan mod budur.
None:Cookie'ye herhangi bir koruma algoritması kullanılmaz.
Encryption: Cookie şifreleme algoritması ile korunur ama veri doğrulama aktif değildir.
Validation: Veri doğruılama aktiftir ama şifreleme aktif değildir.
path Kullanıcının sisteminde Cookie'nin atılacak olduğu yer belirtilebilir.
timeout Kullanıcının sistemine atılan Cookie'nin dakika cinsinden ne kadar geçerli olacağı belirtiliyor. Varsayılan değer 30'dur.
cookieless Cookie kullanılıp kullanılmayacağı belirtiliyor.
domain Cookie'lerin gönderilecek olduğu domain belirtiliyor.
slidingExpiration Kullanılan Cookie'nin zaman aşımı süresinin her çağrıdan sonra yenilenip yenilenmeyeceği belirtiliyor. Varsayılan değer false'tur.
enableCrossAppsRedirect Uygulanan güvenliğin başka bir uygulama tarafından da kullanılıp kullanılamayacağı belirtiliyor. Örneğin bir kaç tane site tasarladınız ve kullanıcı bunların tamamında tek bir parola kullanıyor, bu durumda kullanıcınız sitelerinizin herhangi birinden oturum açtığında bu bilgi diğer sitelerinizde de kullanılabilsin yani kullanıcı yeniden oturum açmak zorunda bırakılmasın var olan oturum diğer siteler için de kullanılabilsin.(Tabi bu durum Cookie adları aynı olduğu durumlarda geçerlidir.)
requireSSL Güvenlik bilgileri iletilirken SSL bağlantısı kullanılıp kullanılmayacağı belirtiliyor.

Bu kadar teknik bilgiden sonra birazcık eğlenelim. Bir tane sayfa hazırlayarak en basit şekilde Form Tabanlı Güvenlik'i nasıl kullanabileceğimize bir göz atalım. İlk olarak aşağıda gördüğünüz kodları konfigürasyon dosyamıza ekleyerek oturum açmamış olan kullanıcıların sistemimize erişmesini yasaklıyor olalım.

<authorization>

<deny users="?"/>

</authorization>

Bu kodları <system.web> tagleri arasına eklediğimizi hatırlayalım. Bir de bir önceki makaleden hatırladığımız kadarıyla ? oturum açmamış olan tüm kullanıcıları temsil ediyordu ve deny'da yasaklama anlamına geliyordu yani bu kodları Türkçe'ye çevirecek olursak, Oturum açmamış olan hiç bir kullanıcıyı bu siteye kabul etme demiş oluyoruz. Yukarıdaki <forms ....> şeklinde olan ayarlara dikkat ettiyseniz loginUrl'i login.aspx olarak belirttik. Kullanıcılarımız bu siteye erişmeye çalıştıklarında eğer oturum açmamışlarsa login.aspx'e otomatik olarak yönlendirileceklerdir. Bu durumda bir tane de login.aspx sayfası tasarlamamız gerekiyor. Sitemize bir tane login.aspx ekleyelim ve sayfaya iki TextBox bir tane de Button sürükleyip bırakalım.

 

Button'un Click eventine aşağıdaki kodları yazalım.

protected void ButtonOturumAc_Click(object sender, EventArgs e)

{

     if (TbKullaniciAdi.Text == "Burak" && TbParola.Text == "1111")

     {

           FormsAuthentication.RedirectFromLoginPage(TbKullaniciAdi.Text, true);

     }

     else

     {

          Response.Write("Yanlış giriş yaptınız...");

     }

}

Yukarıdaki kod bloğu kullanıcının girdiği verileri sorguluyor. Eğer kullanıcı adı Burak'sa ve parola da 1111 ise kullanıcı doğru giriş yapmış olacaktır ve FormsAuthentication sınıfının RedirectFromLoginPage metodu ile kullanıcı login sayfasına yönlendirilmiş olduğu sayfaya yönlendirilecektir. Eğer kullanıcı direkt login.aspx'e gelidyse defaultUrl'de belirtmiş olduğumuz sayfaya yönlendirilecektir. RedirectFromLoginPage metodunun içindeki parametrelin ilki kullanıcı adını, ikincisi ise cookie oluşturulup oluşturmayacağını alıyor. Bu işlemleri yaptıktan sonra uygulamanızı default.aspx sayfasından çalıştırın direkt login.aspx'e yönlendirileceksiniz çünkü henüz oturum açmadınız. Login.aspx'te gerekli bilgileri girdiğinizde ise direkt default.aspx sayfasına yönlendirileceksiniz çünkü login.aspx'e buradan geldiniz.

Projeyi çalıştırdığınızda login.aspx'e gittiğiniz anda URL'e dikkat ederseniz returnUrl'in burada belirtilmiş olduğunu görebilirsiniz.

Güvenlikle ilgili bir şeylerden bahsediyoruz ama sanki burada yanlış bir şeyler var. Kullanıcının şifresini ve parolasını direkt web form da saklamak ne kadar doğrudur acaba! Gelin bu bilgileri buradan kaldıralım.Biz dilersek kullanıcı bilgilerini konfigürasyon dosyamızda depolayabiliriz. Kullanıcı bilgilerini web.config dosyasında saklamak web formda saklamaktan kesinlikle daha güvenlidir çünkü web.config dosyalarına web üzerinden erişmek mümkün değildir. SiteAdi/web.config yazdığımızda bu dosyanın gösterilmesinin yasak olduğunu belirten bir uyarı ile karşılaşırız. Web.config dosyamızda <forms ....> şeklinde ayar yaptımız bölümü aşağıdaki gibi değiştirerek kullanıcının bilgilerini buraya ekleyelim.

<authentication mode="Forms">

<forms loginUrl="login.aspx" name="AspNetGuvenlikDemo" defaultUrl="default.aspx" >

<credentials passwordFormat="Clear" >

<user name="Burak" password="1111"/>

</credentials>

</forms>

</authentication>

Kullanıcı bilgilerini web.config dosyasına ekledik. Koda dikkat ederseniz. forms elemanı altında bulunan Credentials elemanı altında kullanıcılarımızı ekliyoruz, passwordFormat alanını da Clear olarak ayarlayarak parolayı clear text olarak gireceğimizi belirtiyoruz. Bu alanda istediğimiz kadar kullanıcı ekleyebiliriz. Şimdi sıra geldi Button'un click eventindeki kodu güncellemeye, Login.aspx.cs'i açalım ve Buttonun click eventini aşağıdaki gibi ayarlıyor olalım.

protected void ButtonOturumAc_Click(object sender, EventArgs e)

{

     if (FormsAuthentication.Authenticate(TbKullaniciAdi.Text,TbParola.Text))

     {

          FormsAuthentication.RedirectFromLoginPage(TbKullaniciAdi.Text,true);

     }

     else

     {

          Response.Write("Yanlış giriş yaptınız...");

     }

}

Kodlara dikkatlice baktığımızda sadece if'in içinde bulunan ifadeyi değiştirdiğimize dikkat etmiş olmalısınız.Kullanıcı adı ve parolayo web.config'e gömdüğüme göre artık burada bunları tutmamın bir anlamı olmayacaktır. FormsAuthentication sınıfının Authenticate metodu web.config'deki bilgilere göre oturum açma işlemini gerçekleştirir. İlk parametre olarak kullanıcı adını, ikinci parametre olarak ise parolayı alır.Eğer doğru kullanıcı adı ve parola kombinasyonu web.config dosyasında var ise bu metot geriye true değeri döndürür. Uygulamamızı çalıştırıp test ettiğimizde az önceki gibi çalıştığını göreceğiz.

Bu işlemlerden sonra kod bloğumuz biraz daha güvenli hale geldi ama ya herhangi bir kişi bir şekilde web.config dosyasını ele geçirirse ne olacak? Buyurun size bir güvenlik açığı daha. Sitemizi daha güvenli hale getirmeliyiz. web.config dosyasını ele geçiren bir kişi kullanıcı adını görse bile parolayı görmemeli ki sisteme buradaki kullanıcılarla giriş yapamasın.(Aslında herhangi bir kişi web.config dosyasını ele geçirecek kadar sisteminize girebilmişse yapılabilecek pek bir şey yoktur. Oturup dua etmeye başlamalı ve yedek dosyalarınızı aramaya başlamalısınız. Eğer yedeğiniz yoksa içecek soğuk bir şeyler almak için herhangi bir markete doğru yola koyulun :) . ) web.config dosyasını gören bir kişinin buradaki parolaları görmesini engellemek için parolaları web.config dosyasına hashlenmiş olarak kayıt edebiliyoruz. .NET Framework bize bu alanda kullanmak için iki adet Hash formatı sunuyor bunlar SHA1 ve MD5. İkisinin de ortak özelliği buradaki bilgilere göre gerçek şifreye geri dönülemiyor olması. Yani herhangi biri bu verileri alsa bile bir şey yapamıyor. (Her ne kadar böyle söylesem de çok uzun işlemler sonucunda bir şekil de geri döndürülebildiği durumlar da mevcut.) Şimdi kafanızda şöyle bir soru işareti oluşmuştur: Ben herhangi bir şeyin SHA1 veya MD5 karşılığını nereden bileceğim? Microsoft bunu da düşünmüş merak etmeyin. Sitemize yeni bir tane sayfa ekleyelim ve içine bir TextBox, iki label ve bir tane de Button sürükleyip bırakalım.

Şimdi de Button'un Click eventine aşağıdaki kodları yazalım.

protected void Button1_Click(object sender, EventArgs e)

{

     LabelMD5.Text = FormsAuthentication.HashPasswordForStoringInConfigFile(TextBox1.Text, "MD5");

     LabelSHA1.Text = FormsAuthentication.HashPasswordForStoringInConfigFile(TextBox1.Text, "SHA1");

}

 FormAuthentication sınıfındaki HashPasswordForStoringInConfigFile metodu bize istediğimiz herhangi bir stringin belirttiğimiz formattaki karşılığını bize döndürür. Bakalım 1111 değerinin her iki formattaki değeri neymiş?

Şimdi sıra geldi web.config dosyamızda hangi algoritmayı kullanalım sorusuna. MD5 daha hızlı çalışırken SHA1 daha yavaş çalışıyor ama çözülmesi çok daha zor ihtiyacınıza göre istediğiniz birini kullanabilirsiniz. Ben SHA1'ı tercih ediyorum ve web.config dosyasındaki credentials bölümünü aşağıdaki gibi ayarlıyorum.

<authentication mode="Forms">

<forms loginUrl="login.aspx" name="AspNetGuvenlikDemo" defaultUrl="default.aspx" >

<credentials passwordFormat="SHA1">

<user name="Burak" password="011C945F30CE2CBAFC452F39840F025693339C42"/>

</credentials>

</forms>

</authentication>

Gördüğünüz gibi uygulamamızı daha güvenli bir hale getirdik. Kullanıcı adlarını ve parolalarını konfigürasyon dosyamızda kolayca depolayabiliyoruz ama dilersek herhangi bir veri tabanı uygulamasında da depolayabilirdik. Yapacağımız tek değişiklik tahmin ettiğiniz gibi login.aspx'te olacak. Kullanıcı adı ve parolayı sorgulayıp eğer doğru ise kullanıcıyı sisteme kabul edeceğiz.

Dosyaya Özel Güvenlik Ayarı

Şu anda kadarki yapmış olduğumuz ayarlar sitemizin tamamı için geçerliydi, sitemize gelen tüm kullanıcılar herhangi bir sayfaya erişmek istediklerinde güvenlik kontrolünden geçmeleri gerekiyordu ancak biz bazı durumlarda kullanıcıların bazı sayfalara oturum açmadan erişmesini isteyebiliriz. Bunu bir örnekle açıklayacak olursak online alış veriş sitesi yaptığınızı düşünün, bu durumda ziyaretçileriniz oturum açmadan ürünleri listeleyip özelliklerini görebilmeli ama ürün almaya karar verdiklerinde sipariş vermek için oturum açmalıdırlar. Biz şu anda kadar geliştirdiğimiz örneğimize geri dönelim. Bir önceki bölümde yeni bir tane sayfa ekleyip girilen metnin hashlenmiş karşılığını kullanıcıya göstermiştik şimdi dilerseniz sadece bu sayfa için kullanıcının bilgilerini isteyelim, diğer sayfalar tüm ziyaretçilere açık olsun. Bu işlem için ilk olarak konfigürasyon dosyamızdan <authorization> ..... </authorization> bölümüne yazmış olduğumuz kodları kaldıralım ve sitemizin tüm sayfalarını tekrar anonim kullanıcılar için açık hale getirelim.

<authorization>

<deny users="?"/> (Bu satırı kaldırıyoruz!)

</authorization>

Aşağıdaki kodlar ile de sadece HashOgren.aspx sayfası için oturum açmayı gerektirecek olan aşağıdaki kodları <configuration>......</configuration> tagleri arasında konfigürasyon dosyamıza ekleyelim.

<location path="HashOgren.aspx">

   <system.web>

     <authorization>

          <deny users="?"/>

     </authorization>

   </system.web>

</location>

<location> ile hangi sayfa için güvenlik ve yetkilendirme ayarı yapacağımızı belirtiyoruz. <location> kod bloğu arasında bulunan kodlar ise iki makaledir üzerinde konuşmuş olduğumuz kodlardan farklı değil.

Bunların dışında ASP.NET 2.0'la birlikte bize güvenlik yönetimi için yeni kontroller de sunuldu SQL Server Express ile sadece sürükle bırak yöntemi ile sitemizi güvenlik için ayarlayabiliyoruz. Bu iki makale dizisinin amacı ASP.NET 2.0'daki güvenlik mekanizmasını kavratmaktı. Bir sonraki makalemde Membership'i anlatıyor olacağım.Umarım bu iki makale faydalı olmuştur.

Burak Batur
www.burakbatur.com

Kaynak: MSDN, Wrox - Professional Asp Net 2.0 - 2006, Microsoft Press Microsoft Asp Dot Net 2.0 Step By Step Aug 2005, Introducing ASP.NET 2.0