.NET içinde Active Directory işlemleri

C#, VB.NET, ASP.NET Add comments

.NET destekli programlama dillerini kullanarak Active Directory(AD) üzerinde sorgulamalar yapabiliriz. Bu amaçla .NET Framework, System.DirectoryServices kütüphanesini sunar. Bu kütüphanenin sınıflarını kullanarak, AD üzerinde sorgulamalar yapılabilir, ilgili nesnelere ulaşılabilir, kullanıcıların authentication işlemi sağlanabilir, web/windows/console uygulamalarından AD kayıt güncellemeleri gerçekleştirilebilir. DirectoryServices kütüphanesinin sınıflarına geçmeden önce AD’nin desteklediği LDAP standartından bahsedelim.

LDAP (Lightweight Directory Access Protocol),TCP/IP üzerinde çalışan dizin servislerini sorgulamak ve düzeltmek için kullanılan bir ağ iletişim kuralıdır. Bir dizin mantıksal ve sıralı olarak düzenlenmiş benzer özellikteki bilgiler topluluğudur.Dizine en yaygın örnek telefon rehberidir.Bir telefon rehberinde kişiler veye kurumlar alfabetik olarak dizilmiş isimler ile adresler ve telefon numaralarından oluşur. LDAP özellikle kurum içi personelin kayıtlarının tutulabileceği elverişli bir ortam sunar. Bir kurumda çalışanlara çeşitli servisler sunmanız gerekir. Bunun için her servisin üzerinde çalıştığı makinada ayrı ayrı kullanıcı hesapları açmanız gerekebilir. LDAP kullanarak bu sorun çözülebilir.Kuruma giren personel için LDAP sunucusuna tek bir giriş eklersiniz ve LDAP desteği veren servislerin bu sunucu üzerinden kullanıcı bilgilerine erişim ve doğrulama yapmalarını sağlayabilirsiniz. LDAP, Tcp Port’larından 389′u kullanır, blindrequest, addrequest, delrequest, modifyrequest vs. komutları olan bir iletişim kuralıdır. LDAP; Microsoft ve diğer işletim sistemlerinde Active Directory ile sorunsuz çalışan bir iletişim kuralıdır.
LDAP hiyerarşik yapıda ayrıntılı olarak nitelik bilgilerinin tutulduğu ve genellikle okuma hakkı ile erişilen veri tabanıdır. Bu veri tabanı içerisinde tutulan bilgiler; gruplar, nesneler, nesne sınıfları, kişi, grup, organizasyon nesne gruplarına ait isim, soyisim, e-posta adresi, tel, kullanıcı ev dizini gibi alt bilgilerdir. Aslında Active Directory de LDAP yapısı üzerinde çalışmakla birlikte Unix/Linux sistemlerinde çalışan LDAP ile uyumlu değildir. Değişik LDAP servisi veren yazılımlar olmasına rağmen, açık kaynak kodlu Open LDAP servisi yazılımına http://www.openldap.org adresinden erişilip kurulumu ve yapılandırması gerçekleştirilebilir. Belirtilen site adresinde ve değişik pek çok yerde yazılımla ilgili bol miktarda ayrıntılı belge mevcuttur.

LDAP, tam olarak bir database mimarisine sahip olmasa da hiyerarşik düzende bir database yapısına yakın olduğu için sorgulanması ve üzerinde işlem yapılması kolaydır. LDAP servisi kullanılarak, kullanıcı adı ve şifre ikilisiyle merkez sistemden yetki alınarak merkez sistem üzerindeki nesnelere, sistem bilgilerine, diğer kullanıcılara, domainde olan makinelere erişilebilir.

System.DirectoryServices namespace, AD servisiyle ilgili birçok sınıf içerir. Bunlardan en çok kullanılan iki temel sınıf; DirectoryEntry ve DirectorySearcher classlarıdır. DirectoryEntry sınıfı, Active Directory hiyerarşisindeki bir node veya nesneyi erişmemizi sağlar. Bu sınıfın overlaod edilmiş constructörü, genellikle ulaşılacak merkez sistem adresini, kullanıcı adı ve şifre parametrelerini aldığı versiyonuyla kullanılır. DirectorySearcher sınıfı, Active Directory üzerinde çalışacak sorgulamayı hazırlar. AD’nin bulunduğu merkezi sistemin pathini LDAP standartına göre veriyoruz. Yani LDAP://SunucuAdi/HiyerarsidekiNodeAdi şeklinde uzaktaki sunucuyu işaret edebiliriz. Bu yazıda, örneklerle .NET Framework’ün ilgili sınıf ve üyelerini işleyeceğiz.

//AD'ye bağlan
DirectoryEntry objDe = new DirectoryEntry("LDAP://", "", "<Şifre>");
//Sunucu hakkında bilgi alalım.
Response.Write("Sunucu Adı :" + objDe.Name + " Guid : " + objDe.Guid);

//Bulunduğumuz hiyerarşideki düğümleri listeyelim.
foreach (DirectoryEntry Child in objDe.Children)
{
    Response.Write(Child.SchemaClassName + ": " + Child.Name);
}

Bulunduğumuz nodetaki tüm propertylere ve değerlerine erişmek için iç içe bir döngü oluşturmak gerekir. Aşağıdaki kod yardımıyla bu hiyerarşik yapıyı yazdırabiliriz.

PropertyCollection Pc = objDe.Properties;
foreach (string prName in Pc.PropertyNames)
{
  foreach (object value in objDe.Properties[prName])
    Response.Write("property = "+ prName +"   value ="+ value );
}

Active Direcory üzerindeki nesneleri sorgulamak için DirectorySearcher sınıfı kullanılır. Bu sınıfın Filter propertysinde LDAP Search Filter Syntax’ına uygun ifadeler girilerek kayıtlara erişebiliriz.RFC2254 standartına göre kullanılan LDAP arama ifadelerinden bazıları şunlardır;

Arama filtresi Açıklama
“(objectClass=*)” All objects.
“(&(objectCategory=person)(objectClass=user)(!cn=andy))” “andy” dışındaki tüm userlar
“(sn=sm*)” surname niteliği “sm” ile başlayan nesneler
“(&(objectCategory=person)(objectClass=contact)(|(sn=Smith)(sn=Johnson)))” Soyadı, “Smith” veya “Johnson” olan tüm contact userler

Bu ifadelerle ilgili detaylı bilgiyi http://msdn2.microsoft.com/en-us/library/aa746475.aspx adresinde bulabilirsiniz.
Sunucu üzerinde tanımlı makineleri listeyelim. Bunun için AD üzerindeki Computer nesnesini sorgulayacağız.

DirectorySearcher ObjSrch = new DirectorySearcher(objDe);
ObjSrch.Filter = "(objectClass=Computer)";

StringBuilder objStr = new StringBuilder();

foreach (SearchResult Srch in ObjSrch.FindAll())
{
    objStr.Append(Srch.GetDirectoryEntry().Name.ToString());
}

Response.Write(objStr.ToString());

Sorgulanan bilgileri sıralamak için SortOption sınıfı kullanılır. Kayıtların tüm propertylerini değil de belirli propertylerini getirmek için PropertiesToLoad property kullanılır. Şu şekilde bir sorgulama yapalım. Firma.Com.Tr isimli sunucu üzerindeki Merkez isimli node altındaki IT düğümünü sorgulayalım. Bu düğümde Adı, “Ahmet” olan kişilerin mail ve telefon bilgilerini getirelim. Bunu da e-mail adresline göre A’dan Z’ye doğru sıralayalım.

//Konumlanacağımız klasörün pathini verelim.
    DirectoryEntry objDe = new DirectoryEntry("LDAP://Firma/OU=IT,OU=Merkez,DC=Com,DC=Tr","", "<Şifre>");
//Bir arayıcı nesne oluşturalım.
DirectorySearcher searcher = new DirectorySearcher(objDe);
//person isimli nesneyi ve Adı, Ahmet olanlanları arayacak.
searcher.Filter = "(&(objectClass=person)(givenName=Ahmet))";
//mail ve telefon bilgilerini listeye eklesin.
searcher.PropertiesToLoad.Add("mail");
searcher.PropertiesToLoad.Add("telephoneNumber");

//Bir sıralayıcı nesnesi tanımlayalım.
SortOption Srt;
Srt = new SortOption("mail", System.DirectoryServices.SortDirection.Ascending);
searcher.Sort = Srt;
//Sonuçları bir değişkene atalım.
SearchResultCollection Results = searcher.FindAll();

string SearchPath;
foreach (SearchResult Result in Results)
{
    SearchPath = Result.Path;
    Response.Write("Path:" + SearchPath);
    ResultPropertyCollection Rpc = Result.Properties;
    foreach (string Property in Rpc.PropertyNames)
    {
        foreach (object Value in Rpc[Property])
            Response.Write("Property =" + Property + "  Value =" + Value);
    }
}

Aynı mantıkla DirectoryEntry sınıfının CommitChanges metodu kullanılarak property değerleri üzerinde modify işlemleri yapılabilir.
Uygulamalarımıza giriş yaptırırken kullanıcıların doğrudan AD üzerindeki bilgilerle login olmasını sağlayabiliriz. Böylece şirket içerisindeki personel her uygulama için şifre oluşturmak zorunda kalmaz. Aynı güvenlik bilgileriyle hem makinesine logon olur hem maillerini OWA üzerinden okur hem de uygulamamıza giriş yapmış olur. Bu işlemleri yapmak için özel birşey yapmamıza gerek yok. Yukarıda DirectoryEntry nesnesini tanımladığımız satırda kullanıcının girmiş olduğu bilgilerle AD’ye giriş yapmaya çalışırız dönecek değere göre kullanıcıyı içeri alır veya almayız. Kullanıcı adı veya şifre yanlış olduğu zaman AD’den aşağıdaki hata mesajı döner.Logon failure: unknown user name or bad password.
Active Direcory ile ilgili işlemleri yapmak için projemize System.DirectoryServices kütüphanesini ekleyemi unutmamalıyız.

20 Responses to “.NET içinde Active Directory işlemleri”

  1. Ali Gülgönül Says:

    Ahmet Hocam, eline sağlık çok işime yaradı…
    Teşekkürler.

  2. Umut YILMAZ Says:

    Çok aydınlatıcı bir yazı olmuş, benim de gerçekten çok işime yaradı.

    Türkçe olması da ayrıca çok önemli.

    Teşekkürler.

  3. Mustafa Torun Says:

    bu konuyu bu kadar açık anlattığınız için teşekkürler

  4. atilla Says:

    merhabalar ben yazmış olduğum kodda şu hatayı alıyorum b konuda bana yardım edebilir misiniz

    “System.DirectoryServices.DirectoryServicesCOMException: Sunucudan bir başvuru döndürüldü”.

    hatanın geldiği kod parçacığı ise
    string rootDN = (string)(rootDSE.Properties["defaultNamingContext"].Value);
    burada yukarıdaki hatayı veriyor nedeni nedir hocam ?

  5. Ahmet Kaymaz Says:

    A referral was returned from the server hatası belirgin bir hata olduğu için tüm kodları görmeden birşey diyemeyeceğim ancak sorgulanan verilerle sorguyu yapan kullanıcının aynı domain olmaması veya birden fazla domaini sorguluyor olmak veya DirectoryEntry olmadan arama yapmak bu hataya neden olabilir. DirectoryEntry içerisindeki pathi dinamik oluşturmak yerine doğrudan Domain’in direk rootunu gösteren pathini yazarak denemek hatayı düzeltebilir.

  6. Fatih Says:

    Merhaba,
    Öncelikle teşekkür ederim böyle bir bilgiyi bizlerle paylaştığınız için.Bir sorum olucaktı benim yaptığınız örneği aynı ağ içinde iken server ımın IP sini yazarak erişebiliyorum fakat farklı ağda olduğumuz zaman server a mı erişemiyorum.İç ağda iken mesela 192.168.2.200 diyip domain name kısmını bağlanıyorum dış ağda iken bizim ulaşmak istediğim server ın çıkış IP sini yazıyorum ama ulaşamıyo tabi kullanıcı adı şifre giriyorum dışardan erişmek için ne yapmak gerekiyor acaba.

    TESEKKURLER

  7. Ahmet Kaymaz Says:

    Merhaba Fatih,

    AD’nizin dışarıdan erişilebilir olması gerekir. Bu konuda sistem yöneticiniz sizin yönlendirebilir diye düşünüyorum. .NET üzerinden erişmeden önce piyasadaki LDAP Browser, LDAP Administrator gibi programları kullanarak uzaktan erişmeyi denemende fayda vardır.

  8. Fatih Says:

    Çok teşekkür ederim ama benim .net üzerinden erişmem gerek.ldap browser ile denedim ama yine ulaşamadım sistem lerle ilgilenen arkadaşda benim gibi yeni başladı bu işlere server da yapılması gereken ayarlar varmı benim dışardan erişmem için.içerden erişmek için
    path=”ldap://192.168.2.100″,”user”,”sifre” yaziyorum erişiyorum ama dışarıdan
    path=”ldap://CıkısIP”,”user”,”sifre” yazıyorum olmuyo bu konu hakkında bilginiz varsa çok minnettar kalırız.

    TESEKKURLER

  9. Ahmet Kaymaz Says:

    Global Catalog ve LDAP sorguları için 389 ve 3268 portlarını dışarıya açık olması gerekir. Yani sunucunuzun LDAP için gerekli olan portlarını dışarıya açmanız gerekiyor ki oradan sorgulama yapabilesiniz. Ama bunun da beraberinde ciddi güvenlik riski meydana getireceğini unutmamalısınız. Aşağıdaki sitedeki ilgili port ve güvenlik durumlarını görebilirsin.

    http://technet.microsoft.com/en-us/library/cc978012.aspx

  10. Fatih Says:

    Çok Teşekkür ederim 3268 portunu açınca istediğimiz oldu tabi güvenli olup olmayacağına iyice araştırmak gerekiyor.

    LDAP://CıkısIP:3268 diye belirtince path kısmına oldu.

    Kolay Gelsin

    TEŞEKKÜRLER

  11. onur Says:

    Aynı güvenlik bilgileriyle hem makinesine logon olur hem maillerini OWA üzerinden okur hem de uygulamamıza giriş yapmış olur. Bu işlemleri yapmak için özel birşey yapmamıza gerek yok. Yukarıda DirectoryEntry nesnesini tanımladığımız satırda kullanıcının girmiş olduğu bilgilerle AD’ye giriş yapmaya çalışırız dönecek değere göre kullanıcıyı içeri alır veya almayız…
    yazdığınız kısmı kodlayabilir misiniz..tam olarak nasıl yazmamız gerekir…teşekkürler

  12. Ahmet Kaymaz Says:

    Bu cümlelerden kastım bunlardan hemen önceki cümledir; “Uygulamalarımıza giriş yaptırırken kullanıcıların doğrudan AD üzerindeki bilgilerle login olmasını sağlayabiliriz. Böylece şirket içerisindeki personel her uygulama için şifre oluşturmak zorunda kalmaz.” Yani hem intranet hem OWA hem de makinesine logon olmak kullanıcı AD üzerinde bir account açmak yeterli olacaktır. Her uygulamaya özgü şifre vermemiş oluruz. Yazıdaki ilk kod alanı, .NET uygulaması içerisinde nasıl AD’de kullanıcı sorgulanacağını içermektedir.

  13. onur Says:

    Temel problemim bilgisayar şifresini girdiklerinde bunu web sitesindeki koda nasıl entegre edip ona göre id alırım…bu id ye göre kiiye özel vt işlemleri gereçekleştirmeye çalışacam…Yukarıdaki ilk kodla bunu nasıl konuşturabilirim…

  14. Ahmet Kaymaz Says:

    Veritabanında User tablosu olacak. Her akşam AD’den kullanıcıları alıp bu tabloya aktaracak bir EXE programı yazacaksın. AD’den gelen kullanıcılar daha önce tabloda mevcut ise birşey yapmayacaksın yoksa INSERT işlemi yapacaksın. Dolayısıyla her kullanıcıya kendi uygulaman tarafında bir ID vermiş olursun.

  15. İzzet Says:

    Çok faydalı bir makale. Elinize, aklınıza sağlık..

  16. Mehmet Y Says:

    Ahmet bey öncelikle örnek için sağolun. Sorum şu;
    Active Directory ile kullanıcın logonhours unu nasıl değiştirebilirim, teşekkürler.

  17. Ahmet Kaymaz Says:

    Mehmet Bey,

    “NET USE” komutu ile aşağıdaki gibi değiştirebilirsin.

    NET USER USER_NAME /TIMES:MONDAY,TUESDAY,2

    Konuyla ilgili detay şu linktedir;

    http://support.microsoft.com/default.aspx?scid=kb;en-us;179450

    Aynı şekilde VBScript ile bu işlemi yapmak aşağıdaki dosyada anlatılan komut serisi yardımcı olabilir.

    http://www.sd61.bc.ca/windows2000/Docs/VBScriptDir.doc

    .NET’te bu işlemi yapmak için DirectoryEntry.Invoke() ile çağrılabilecek bir yordama denk gelmedim. Aklıma başka bir yöntem gelirse yazarım. Invoke() yordamıyla çağrılabilecek ADSI arabirimleri aşağıdaki adreslerde listelenmiştir;

    http://msdn.microsoft.com/library/en-us/adsi/adsi/iadsuser.asp

    http://msdn.microsoft.com/library/en-us/adsi/adsi/iadsgroup.asp

    http://msdn.microsoft.com/library/en-us/sds/sds/list_of_adsi_interfaces_to_invoke.asp

  18. Mehmet Y Says:

    Ahmet Bey cevabınız için sağolun,
    Net user komutunu .net içinde shell e çağırmayı denemiştim ki bu komutu sadece lokal kullanıcılar için kullanabildim, domaindeki kullanıcılarda kullanamadım, sanırım komutun direkt dc üzerinden kullanılması gerekiyor ama benim kullandığım bilgisayar dc değil sadece domaine dahil Active Directory User and Computers kurulu olduğu bir makina. AD de üzerinden değiştirmeme rağmen net user ile kullanıcı bulunamadı diyor. Teşekkürler

  19. Murat Says:

    Selamlar
    Bu faydalı yazınız için teşekkür ederim.
    AD ile ilgili bir sorum olacak.
    AD ye ait loglar nerede tutulur ve bu loglara c# ile ulaşmanın bir yolu var mıdır?
    Kolay Gelsin…

  20. Ahmet Kaymaz Says:

    Murat,

    bu konuda uzman sayılmam. AD’nin kendi log dosyalarını (NTDS klasörünün altındaki log, dit dosyası) Microsoft Log Parser ile okuyabilirsin. C# konusunda bir yorum yapamayacağım.

Leave a Reply

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Giriş