.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.




Kasım 12th, 2007 at 16:59
Ahmet Hocam, eline sağlık çok işime yaradı…
Teşekkürler.
Temmuz 4th, 2008 at 15:50
Ç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.
Aralık 20th, 2008 at 10:34
bu konuyu bu kadar açık anlattığınız için teşekkürler
Şubat 26th, 2009 at 16:44
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 ?
Şubat 27th, 2009 at 09:44
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.
Nisan 9th, 2009 at 09:35
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
Nisan 9th, 2009 at 11:55
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.
Nisan 9th, 2009 at 15:09
Ç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
Nisan 10th, 2009 at 13:47
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
Nisan 13th, 2009 at 08:47
Ç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
Eylül 2nd, 2009 at 15:22
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
Eylül 3rd, 2009 at 21:56
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.
Eylül 8th, 2009 at 14:09
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…
Eylül 10th, 2009 at 07:34
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.
Ocak 4th, 2010 at 17:42
Çok faydalı bir makale. Elinize, aklınıza sağlık..
Ocak 25th, 2010 at 00:29
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.
Ocak 25th, 2010 at 09:15
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
Ocak 28th, 2010 at 11:18
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
Şubat 11th, 2010 at 10:19
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…
Şubat 12th, 2010 at 17:16
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.
Ocak 24th, 2011 at 12:07
Selamlar Ahmet Bey, öncelikle çok teşekkür ederim , çok acıklayıcı bir yazı olmuş.Bu konuda size danışmak istediğim bir şey olucaktı , “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.” şeklinde açıklamış olduğunuz kısma istinaden , kendi projemdede aynı uyarıyı alıyorum , fakat kullanıcı adı ve şifrem doğru,herzaman kullandığım kullanıcı adı ve şifre.Birde bir keresinde daha farklı bir hata verdi ,
The server is not operational şeklinde, amacım , login olunması gereken bir uygulamanın, login kısmında , kullanıcının kendi domaindeki kullanıcı adı ve şifresini girdiği an panel’e erişebilmesi.Böyle bir şeyi nasıl tanımlayabilirim , belkide baştan tamamen yanlış yapıyorum , bu konuda yönlendirici bir bilgi verebilirseniz çok sevinirim.Kolay Gelsin, İyi Çalışmalar…
Ocak 25th, 2011 at 12:09
Berkan Bey,
eğer o hata mesajı geliyorsa güvenlik bilgileriniz yanlış demektir. Bu bilgilerin doğruluğundan emin olmanız gerekmektedir. Gerekirse domain adını kullanarak kullanıcı adını giriniz. Varsa OWA’ya nasıl giriyorsanız o şekilde yazarsanız olur. Bu proje için doğru seçim yapmışsınız. AD üzerinden giriş yaptıktan sonra paneli açmanız doğru bir işlem.
Aralık 30th, 2011 at 15:01
C# ile active directorydeki computer nesnesine ait bilgileri çekiyorum.Çekitği bilgiler işletim sistemi,ldp ismi,sonb otrum başlama tarihi v.b.Bu bilgisayarların donanımsal bilgilerine(işlemci modeli,anakart markası v.s.) de erişmem lazım.Bunu nasıl yapabilirim.Bu konuda yardımcı olabilirseniz çok sevinirim şimdiden teşekkürler.
Aralık 31st, 2011 at 22:39
Tari,
Yerel veya uzaktaki bir makine hakkında bilgi almak için WMI (Windows Management Instrumentation) sorgusu yapılmalıdır. WMI, sisteme ait parçaları izlemek için sunulan Windows bileşenler bütünüdür. .NET tarafında WMI ile çalışmak için System.Management namespace sunulmaktadır. Bununla ilgili bir örnek yapmadım ancak ManagementScope sınıfını kullanarak uzaktaki makineye bağlanılabileceğini ve o şekilde sistem sorgulamalarının yapılabileceğini düşünüyorum.
Ocak 2nd, 2012 at 12:21
WMI ile kendi bilgisayarımdaki donanımsal bilgilere erişebiliyorum ancak ManagementScope ile uzaktaki bir makineye bağlanma işini beceremedim maalesef.
Ocak 2nd, 2012 at 16:39
Aşağıdaki sayfada uzaktak makineye erişimle ilgili örnek bulabilirsiniz. Bu şekilde olacağını ümit ediyorum.
http://msdn.microsoft.com/en-us/library/ms257337(v=vs.80).aspx
Ocak 3rd, 2012 at 08:05
Öncelikle cevap için çok teşekkür ederim.İnceledikten ve denedikten sonra sonuçlar hakkında size geri bildirim yapacağım en kısa sürede.
Ocak 6th, 2012 at 16:26
Connection wmiConnection = new Connection(“kullanıcıAdı”,”kullanıcıSifre”,”domainIsmı”,”baglanılmakIstenenBilgisayarIp”); nesnesi bu konuda bana çok yardımcı oldu. Tabi burada kullanılan kullanıcı hesabı admin yetkili bir hesap olmalı.Burada ip scopeunuza göre bir for döngüsü ile ip değerini değişken olarak alıp networkdeki tüm bilgisayarlara ait bilgileri almayı başardım.