Validasi nama pengguna dan kata sandi terhadap Active Directory?

526

Bagaimana saya bisa memvalidasi nama pengguna dan kata sandi terhadap Active Directory? Saya hanya ingin memeriksa apakah nama pengguna dan kata sandi sudah benar.

Marc
sumber

Jawaban:

642

Jika Anda bekerja dengan .NET 3.5 atau yang lebih baru, Anda bisa menggunakan System.DirectoryServices.AccountManagementnamespace dan dengan mudah memverifikasi kredensial Anda:

// create a "principal context" - e.g. your domain (could be machine, too)
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
    // validate the credentials
    bool isValid = pc.ValidateCredentials("myuser", "mypassword");
}

Sederhana, dapat diandalkan, 100% kode dikelola # C di ujung Anda - apa lagi yang bisa Anda minta? :-)

Baca semua tentang ini di sini:

Memperbarui:

Sebagaimana diuraikan dalam pertanyaan SO lainnya ini (dan jawabannya) , ada masalah dengan panggilan ini yang mungkin mengembalikan Truekata sandi lama pengguna. Berhati-hatilah dengan perilaku ini dan jangan terlalu terkejut jika ini terjadi :-) (terima kasih kepada @MikeGledhill karena telah menunjukkan ini!)

marc_s
sumber
36
Di domain saya, saya harus menentukan pc.ValidateCredentials ("myuser", "mypassword", ContextOptions.Negotiate) atau saya akan mendapatkan System.DirectoryServices.Protocols.DirectoryOperationException: Server tidak dapat menangani permintaan direktori.
Alex Peck
12
Jika kata sandi kedaluwarsa atau akun dinonaktifkan, maka ValidateCredentials akan kembali palsu. Sayangnya, itu tidak memberi tahu Anda mengapa itu dikembalikan palsu (yang sangat disayangkan karena itu berarti saya tidak bisa melakukan sesuatu yang masuk akal seperti mengarahkan pengguna untuk mengubah kata sandi mereka).
Chris J
64
Waspadalah juga dengan akun 'Tamu' - jika akun Tamu tingkat domain diaktifkan, ValidateCredentials mengembalikan true jika Anda memberikannya sebagai pengguna yang tidak ada . Akibatnya, Anda mungkin ingin menelepon UserPrinciple.FindByIdentityuntuk melihat apakah ID pengguna yang lulus ada terlebih dahulu.
Chris J
7
@AlexPeck: alasan mengapa Anda harus melakukan ini (seperti saya) adalah bahwa .NET menggunakan teknologi berikut secara default: LDAP + SSL, Kerberos, lalu RPC. Saya menduga RPC tidak aktif di jaringan Anda (bagus!) Dan Kerberos tidak benar-benar digunakan oleh .NET kecuali Anda secara eksplisit mengatakannya menggunakan ContextOptions.Negotiate.
Brett Veenstra
5
Perlu diketahui bahwa jika pengguna MENGUBAH kata sandi Active Directory mereka, kode ini akan terus mengotentikasi pengguna dengan senang hati menggunakan kata sandi AD lama mereka. Yup, sungguh. Baca di sini: stackoverflow.com/questions/8949501/…
Mike Gledhill
70

Kami melakukan ini di Intranet kami

Anda harus menggunakan System.DirectoryServices;

Berikut adalah nyali kode

using (DirectoryEntry adsEntry = new DirectoryEntry(path, strAccountId, strPassword))
{
    using (DirectorySearcher adsSearcher = new DirectorySearcher(adsEntry))
    {
        //adsSearcher.Filter = "(&(objectClass=user)(objectCategory=person))";
        adsSearcher.Filter = "(sAMAccountName=" + strAccountId + ")";

        try
        {
            SearchResult adsSearchResult = adsSearcher.FindOne();
            bSucceeded = true;

            strAuthenticatedBy = "Active Directory";
            strError = "User has been authenticated by Active Directory.";
        }
        catch (Exception ex)
        {
            // Failed to authenticate. Most likely it is caused by unknown user
            // id or bad strPassword.
            strError = ex.Message;
        }
        finally
        {
            adsEntry.Close();
        }
    }
}
DiningPhilanderer
sumber
9
Apa yang Anda letakkan di "jalan"? Nama domain? Nama servernya? Jalur LDAP ke domain? Jalur LDAP ke server?
Ian Boyd
3
Jawab1: Tidak, kami menjalankannya sebagai layanan web sehingga dapat dipanggil dari beberapa lokasi di aplikasi web utama. Answer2: Path berisi info LDAP ... LDAP: // DC = domainname1, DC = domainname2, DC = com
DiningPhilanderer
3
Tampaknya ini dapat memungkinkan injeksi LDAP. Anda mungkin ingin memastikan untuk melarikan diri atau menghapus tanda kurung di strAccountId
Brain2000
Apakah ini artinya strPassworddisimpan dalam LDAP dalam teks biasa?
Matt Kocaj
15
Seharusnya tidak ada kebutuhan untuk secara eksplisit menyebut Close()pada usingvariabel.
Nyerguds
62

Beberapa solusi yang disajikan di sini tidak memiliki kemampuan untuk membedakan antara pengguna / kata sandi yang salah, dan kata sandi yang perlu diubah. Itu bisa dilakukan dengan cara berikut:

using System;
using System.DirectoryServices.Protocols;
using System.Net;

namespace ProtocolTest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                LdapConnection connection = new LdapConnection("ldap.fabrikam.com");
                NetworkCredential credential = new NetworkCredential("user", "password");
                connection.Credential = credential;
                connection.Bind();
                Console.WriteLine("logged in");
            }
            catch (LdapException lexc)
            {
                String error = lexc.ServerErrorMessage;
                Console.WriteLine(lexc);
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc);
            }
        }
    }
}

Jika kata sandi pengguna salah, atau pengguna tidak ada, kesalahan akan berisi

"8009030C: LdapErr: DSID-0C0904DC, komentar: Kesalahan acceptSecurityContext, data 52e, v1db1",

jika kata sandi pengguna perlu diubah, itu akan berisi

"8009030C: LdapErr: DSID-0C0904DC, komentar: Kesalahan acceptSecurityContext, data 773, v1db1"

Nilai lexc.ServerErrorMessagedata adalah representasi hex Kode Kesalahan Win32. Ini adalah kode kesalahan yang sama yang akan dikembalikan dengan cara memanggil panggilan API LogonUser Win32. Daftar di bawah ini merangkum berbagai nilai umum dengan nilai hex dan desimal:

525 user not found ​(1317)
52e invalid credentials ​(1326)
530 not permitted to logon at this time (1328)
531 not permitted to logon at this workstation (1329)
532 password expired ​(1330)
533 account disabled ​(1331) 
701 account expired ​(1793)
773 user must reset password (1907)
775 user account locked (1909)
Søren Mors
sumber
2
Sayangnya, beberapa instalasi AD tidak mengembalikan kode kesalahan sub LDAP, yang berarti bahwa solusi ini tidak akan berfungsi.
Søren Mors
4
Jangan lupa untuk menambahkan beberapa referensi ke proyek: System.DirectoryServicesdanSystem.DirectoryServices.Protocols
TomXP411
3
Pertanyaan saya, apakah ini: bagaimana Anda mendapatkan nama server LDAP? Jika Anda menulis aplikasi portabel, Anda tidak dapat mengharapkan pengguna untuk mengetahui atau perlu menyediakan nama server AD pada setiap jaringan.
TomXP411
1
Saya memiliki pengguna yang dibatasi untuk masuk ke workstation tertentu; bagaimana cara menentukan workstation yang saya coba masuk? (workstation1 akan gagal dengan data 531, workstation2 akan berfungsi dengan baik, misalnya)
akohlsmith
1
Saya merasa aneh karena saya tidak berpikir Anda mendapatkan kredit yang cukup. Ini adalah metode yang sepenuhnya dikelola tanpa kesulitan panggilan Win32 API untuk menentukan apakah "pengguna harus mengatur ulang kata sandi" yang jelas tidak ada jawaban lain yang dicapai. Apakah ada celah dalam metode ini yang menyebabkan tingkat apresiasi yang rendah? hmm ...
Lionet Chen
34

solusi yang sangat sederhana menggunakan DirectoryServices:

using System.DirectoryServices;

//srvr = ldap server, e.g. LDAP://domain.com
//usr = user name
//pwd = user password
public bool IsAuthenticated(string srvr, string usr, string pwd)
{
    bool authenticated = false;

    try
    {
        DirectoryEntry entry = new DirectoryEntry(srvr, usr, pwd);
        object nativeObject = entry.NativeObject;
        authenticated = true;
    }
    catch (DirectoryServicesCOMException cex)
    {
        //not authenticated; reason why is in cex
    }
    catch (Exception ex)
    {
        //not authenticated due to some other exception [this is optional]
    }

    return authenticated;
}

akses NativeObject diperlukan untuk mendeteksi pengguna / kata sandi yang buruk

Steven A. Lowe
sumber
4
Kode ini buruk karena ia juga melakukan pemeriksaan otorisasi (periksa apakah pengguna diizinkan membaca informasi direktori aktif). Nama pengguna dan kata sandi bisa valid, tetapi pengguna tidak diizinkan membaca info - dan mendapatkan pengecualian. Dengan kata lain Anda dapat memiliki nama pengguna & kata sandi yang valid, tetapi masih mendapatkan pengecualian.
Ian Boyd
2
Saya sebenarnya dalam proses meminta padanan asliPrincipleContext - yang hanya ada di .NET 3.5. Tetapi jika Anda menggunakan .NET 3.5 atau yang lebih baru, Anda harus menggunakanPrincipleContext
Ian Boyd
28

Sayangnya tidak ada cara "sederhana" untuk memeriksa kredensial pengguna pada AD.

Dengan setiap metode yang disajikan sejauh ini, Anda mungkin mendapatkan false-negative: Kredit pengguna akan valid, namun AD akan mengembalikan false dalam keadaan tertentu:

  • Pengguna diminta untuk Mengubah Kata Sandi pada Logon Selanjutnya.
  • Kata sandi pengguna telah kedaluwarsa.

ActiveDirectory tidak akan mengizinkan Anda menggunakan LDAP untuk menentukan apakah kata sandi tidak valid karena fakta bahwa pengguna harus mengubah kata sandi atau jika kata sandi mereka telah kedaluwarsa.

Untuk menentukan perubahan kata sandi atau kata sandi kedaluwarsa, Anda dapat menghubungi Win32: LogonUser (), dan memeriksa kode kesalahan windows untuk 2 konstanta berikut:

  • ERROR_PASSWORD_MUST_CHANGE = 1907
  • ERROR_PASSWORD_EXPIRED = 1330
Alan
sumber
1
Bolehkah saya bertanya di mana Anda mendapatkan devinitions untuk Expired dan Must_Change ... Menemukan mereka di mana pun kecuali di sini :)
mabstrei
Terima kasih. Saya mencoba mencari tahu cara validasi saya kembali salah sepanjang waktu. Itu karena pengguna perlu mengubah kata sandi.
Deise Vicentin
22

Cara termudah adalah dengan PInvoke LogonUser Win32 API.eg

http://www.pinvoke.net/default.aspx/advapi32/LogonUser.html

Referensi MSDN di sini ...

http://msdn.microsoft.com/en-us/library/aa378184.aspx

Pasti ingin menggunakan tipe masuk

LOGON32_LOGON_NETWORK (3)

Ini membuat token yang ringan saja - sempurna untuk pemeriksaan AuthN. (tipe lain dapat digunakan untuk membuat sesi interaktif, dll.)

stephbu
sumber
Seperti yang ditunjukkan @Alan, LogonUser API memiliki banyak sifat berguna di luar panggilan System.DirectoryServices.
stephbu
3
@cciotti: Tidak, itu salah. Cara TERBAIK untuk mengotentikasi seseorang dengan benar adalah dengan menggunakan LogonUserAPI sebagai @stephbu write. Semua metode lain yang dijelaskan dalam posting ini TIDAK AKAN BEKERJA 100%. Hanya sebuah catatan, saya yakin Anda harus bergabung dengan domain untuk memanggil LogonUser.
Alan
@Lan untuk menghasilkan kredensial Anda harus dapat terhubung ke domain dengan menyerahkan akun domain yang valid. Namun saya cukup yakin mesin Anda tidak perlu menjadi anggota domain.
stephbu
2
The LogonUserAPI mengharuskan pengguna untuk memiliki Bertindak sebagai bagian dari sistem operasi privelage; yang bukan sesuatu yang didapat pengguna - dan bukan sesuatu yang ingin Anda berikan kepada setiap pengguna dalam organisasi. ( msdn.microsoft.com/en-us/library/aa378184(v=vs.85).aspx )
Ian Boyd
1
LogonUser hanya perlu bertindak sebagai bagian dari sistem operasi untuk Windows 2000 dan di bawah ini sesuai dengan support.microsoft.com/kb/180548 ... Terlihat bersih untuk Server 2003 dan lebih tinggi.
Chris J
18

Solusi .Net penuh adalah dengan menggunakan kelas-kelas dari namespace System.DirectoryServices. Mereka memungkinkan untuk meminta server AD secara langsung. Berikut adalah contoh kecil yang akan melakukan ini:

using (DirectoryEntry entry = new DirectoryEntry())
{
    entry.Username = "here goes the username you want to validate";
    entry.Password = "here goes the password";

    DirectorySearcher searcher = new DirectorySearcher(entry);

    searcher.Filter = "(objectclass=user)";

    try
    {
        searcher.FindOne();
    }
    catch (COMException ex)
    {
        if (ex.ErrorCode == -2147023570)
        {
            // Login or password is incorrect
        }
    }
}

// FindOne() didn't throw, the credentials are correct

Kode ini langsung terhubung ke server AD, menggunakan kredensial yang disediakan. Jika kredensial tidak valid, searcher.FindOne () akan melempar pengecualian. ErrorCode adalah yang sesuai dengan kesalahan COM "kesalahan nama pengguna / kata sandi".

Anda tidak perlu menjalankan kode sebagai pengguna AD. Bahkan, saya berhasil menggunakannya untuk menanyakan informasi pada server AD, dari klien di luar domain!

Mathieu Garstecki
sumber
bagaimana dengan tipe otentikasi? saya pikir Anda lupa dalam kode Anda di atas. :-) secara default DirectoryEntry.AuthenticationType diatur ke Dijamin kan? kode itu tidak akan berfungsi pada LDAP yang tidak diamankan (Anonim atau Tidak Ada mungkin). apakah saya benar dengan ini?
jerbersoft
Sisi buruk dari kueri server AD adalah Anda memiliki izin untuk meminta server AD. Kredensial Anda bisa valid, tetapi jika Anda tidak memiliki izin untuk meminta AD, maka Anda akan mendapatkan kesalahan. Itulah mengapa Fast Bind diciptakan; Anda memvalidasi kredensial tanpa mengesahkan kemampuan pengguna untuk melakukan sesuatu.
Ian Boyd
2
tidakkah ini mengizinkan siapa pun untuk lulus jika COMException dilempar karena alasan lain sebelum kredensial diperiksa?
Stefan Paul Noack
11

Namun .NET call lain untuk mengautentikasi kredensial LDAP dengan cepat:

using System.DirectoryServices;

using(var DE = new DirectoryEntry(path, username, password)
{
    try
    {
        DE.RefreshCache(); // This will force credentials validation
    }
    catch (COMException ex)
    {
        // Validation failed - handle how you want
    }
}
palswim
sumber
Ini adalah satu-satunya solusi yang berhasil bagi saya, menggunakan PrincipalContext belum berfungsi untuk saya.
Daniel
PrincipalContext tidak valid untuk koneksi LDAP aman (alias LDAPS, yang menggunakan port 636
Kiquenet
10

Coba kode ini (CATATAN: Dilaporkan tidak berfungsi di windows server 2000)

#region NTLogonUser
#region Direct OS LogonUser Code
[DllImport( "advapi32.dll")]
private static extern bool LogonUser(String lpszUsername, 
    String lpszDomain, String lpszPassword, int dwLogonType, 
    int dwLogonProvider, out int phToken);

[DllImport("Kernel32.dll")]
private static extern int GetLastError();

public static bool LogOnXP(String sDomain, String sUser, String sPassword)
{
   int token1, ret;
   int attmpts = 0;

   bool LoggedOn = false;

   while (!LoggedOn && attmpts < 2)
   {
      LoggedOn= LogonUser(sUser, sDomain, sPassword, 3, 0, out token1);
      if (LoggedOn) return (true);
      else
      {
         switch (ret = GetLastError())
         {
            case (126): ; 
               if (attmpts++ > 2)
                  throw new LogonException(
                      "Specified module could not be found. error code: " + 
                      ret.ToString());
               break;

            case (1314): 
               throw new LogonException(
                  "Specified module could not be found. error code: " + 
                      ret.ToString());

            case (1326): 
               // edited out based on comment
               //  throw new LogonException(
               //   "Unknown user name or bad password.");
            return false;

            default: 
               throw new LogonException(
                  "Unexpected Logon Failure. Contact Administrator");
              }
          }
       }
   return(false);
}
#endregion Direct Logon Code
#endregion NTLogonUser

kecuali Anda harus membuat pengecualian khusus untuk "LogonException"

Charles Bretana
sumber
Jangan gunakan penanganan pengecualian untuk mengembalikan informasi dari suatu metode. "Nama pengguna tidak dikenal atau kata sandi buruk" tidak luar biasa, itu adalah perilaku standar untuk LogonUser. Kembalikan salah.
Treb
ya ... ini adalah port dari perpustakaan VB6 lama ... ditulis tahun 2003 atau lebih ... (ketika .Net pertama kali keluar)
Charles Bretana
Jika berjalan pada Windows 2000 kode ini tidak akan berfungsi ( support.microsoft.com/kb/180548 )
Ian Boyd
1
Memikirkan kembali ini. Logon perilaku yang diharapkan Pengguna, tujuannya, adalah untuk login pengguna . Jika gagal melakukan tugas itu, itu ADALAH pengecualian. Bahkan, metode ini harus mengembalikan void, bukan Boolean. Plus, jika Anda baru saja mengembalikan Boolean, konsumen metode tidak memiliki cara untuk memberi tahu pengguna apa alasan kegagalan itu.
Charles Bretana
5

Jika Anda terjebak dengan .NET 2.0 dan kode terkelola, berikut adalah cara lain yang berfungsi dengan akun lokal dan domain:

using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Diagnostics;

static public bool Validate(string domain, string username, string password)
{
    try
    {
        Process proc = new Process();
        proc.StartInfo = new ProcessStartInfo()
        {
            FileName = "no_matter.xyz",
            CreateNoWindow = true,
            WindowStyle = ProcessWindowStyle.Hidden,
            WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
            UseShellExecute = false,
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            LoadUserProfile = true,
            Domain = String.IsNullOrEmpty(domain) ? "" : domain,
            UserName = username,
            Password = Credentials.ToSecureString(password)
        };
        proc.Start();
        proc.WaitForExit();
    }
    catch (System.ComponentModel.Win32Exception ex)
    {
        switch (ex.NativeErrorCode)
        {
            case 1326: return false;
            case 2: return true;
            default: throw ex;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }

    return false;
}   
chauwel
sumber
Bekerja dengan baik dengan akun lokal dari mesin yang ia luncurkan skrip
eka808
BTW, metode ini diperlukan untuk membuat ini berfungsi publik SecureString ToSecureString statis publik (string PwString) {char [] PasswordChars = PwString.ToCharArray (); SecureString Password = new SecureString (); foreach (char c dalam PasswordChars) Password.AppendChar (c); ProcessStartInfo foo = new ProcessStartInfo (); foo.Password = Kata Sandi; return foo.Password; }
eka808
Sebaliknya, orang harus menggunakan SecureString untuk kata sandi. WPF PasswordBox mendukungnya.
Stephen Drew
5

Otentikasi Windows dapat gagal karena berbagai alasan: nama pengguna atau kata sandi salah, akun terkunci, kata sandi kedaluwarsa, dan banyak lagi. Untuk membedakan antara kesalahan ini, panggil fungsi LogonUser API melalui P / Invoke dan periksa kode kesalahan jika fungsinya kembali false:

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

using Microsoft.Win32.SafeHandles;

public static class Win32Authentication
{
    private class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle() // called by P/Invoke
            : base(true)
        {
        }

        protected override bool ReleaseHandle()
        {
            return CloseHandle(this.handle);
        }
    }

    private enum LogonType : uint
    {
        Network = 3, // LOGON32_LOGON_NETWORK
    }

    private enum LogonProvider : uint
    {
        WinNT50 = 3, // LOGON32_PROVIDER_WINNT50
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr handle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(
        string userName, string domain, string password,
        LogonType logonType, LogonProvider logonProvider,
        out SafeTokenHandle token);

    public static void AuthenticateUser(string userName, string password)
    {
        string domain = null;
        string[] parts = userName.Split('\\');
        if (parts.Length == 2)
        {
            domain = parts[0];
            userName = parts[1];
        }

        SafeTokenHandle token;
        if (LogonUser(userName, domain, password, LogonType.Network, LogonProvider.WinNT50, out token))
            token.Dispose();
        else
            throw new Win32Exception(); // calls Marshal.GetLastWin32Error()
    }
}

Penggunaan sampel:

try
{
    Win32Authentication.AuthenticateUser("EXAMPLE\\user", "P@ssw0rd");
    // Or: Win32Authentication.AuthenticateUser("[email protected]", "P@ssw0rd");
}
catch (Win32Exception ex)
{
    switch (ex.NativeErrorCode)
    {
        case 1326: // ERROR_LOGON_FAILURE (incorrect user name or password)
            // ...
        case 1327: // ERROR_ACCOUNT_RESTRICTION
            // ...
        case 1330: // ERROR_PASSWORD_EXPIRED
            // ...
        case 1331: // ERROR_ACCOUNT_DISABLED
            // ...
        case 1907: // ERROR_PASSWORD_MUST_CHANGE
            // ...
        case 1909: // ERROR_ACCOUNT_LOCKED_OUT
            // ...
        default: // Other
            break;
    }
}

Catatan: LogonUser membutuhkan hubungan kepercayaan dengan domain yang Anda validasi.

Michael Liu
sumber
dapatkah Anda menjelaskan mengapa jawaban Anda lebih baik daripada jawaban pilihan tertinggi?
Mohammad Ali
1
@MohammadAli: Jika Anda perlu tahu mengapa validasi kredensial gagal (kredensial salah, akun terkunci, kata sandi kedaluwarsa, dll.), Fungsi LogonUser API akan memberi tahu Anda. Sebaliknya, metode PrincipalContext.ValidateCredentials (menurut komentar pada jawaban marc_s) tidak akan; itu mengembalikan false dalam semua kasus ini. Di sisi lain, LogonUser membutuhkan hubungan kepercayaan dengan domain, tetapi PrincipalContext.ValidateCredentials (saya pikir) tidak.
Michael Liu
2

Fungsi Sederhana Saya

 private bool IsValidActiveDirectoryUser(string activeDirectoryServerDomain, string username, string password)
    {
        try
        {
            DirectoryEntry de = new DirectoryEntry("LDAP://" + activeDirectoryServerDomain, username + "@" + activeDirectoryServerDomain, password, AuthenticationTypes.Secure);
            DirectorySearcher ds = new DirectorySearcher(de);
            ds.FindOne();
            return true;
        }
        catch //(Exception ex)
        {
            return false;
        }
    }
hossein andarkhora
sumber
1

Di sini solusi otentikasi lengkap saya untuk referensi Anda.

Pertama, tambahkan empat referensi berikut

 using System.DirectoryServices;
 using System.DirectoryServices.Protocols;
 using System.DirectoryServices.AccountManagement;
 using System.Net; 

private void AuthUser() { 


      try{
            string Uid = "USER_NAME";
            string Pass = "PASSWORD";
            if (Uid == "")
            {
                MessageBox.Show("Username cannot be null");
            }
            else if (Pass == "")
            {
                MessageBox.Show("Password cannot be null");
            }
            else
            {
                LdapConnection connection = new LdapConnection("YOUR DOMAIN");
                NetworkCredential credential = new NetworkCredential(Uid, Pass);
                connection.Credential = credential;
                connection.Bind();

                // after authenticate Loading user details to data table
                PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
                UserPrincipal user = UserPrincipal.FindByIdentity(ctx, Uid);
                DirectoryEntry up_User = (DirectoryEntry)user.GetUnderlyingObject();
                DirectorySearcher deSearch = new DirectorySearcher(up_User);
                SearchResultCollection results = deSearch.FindAll();
                ResultPropertyCollection rpc = results[0].Properties;
                DataTable dt = new DataTable();
                DataRow toInsert = dt.NewRow();
                dt.Rows.InsertAt(toInsert, 0);

                foreach (string rp in rpc.PropertyNames)
                {
                    if (rpc[rp][0].ToString() != "System.Byte[]")
                    {
                        dt.Columns.Add(rp.ToString(), typeof(System.String));

                        foreach (DataRow row in dt.Rows)
                        {
                            row[rp.ToString()] = rpc[rp][0].ToString();
                        }

                    }  
                }
             //You can load data to grid view and see for reference only
                 dataGridView1.DataSource = dt;


            }
        } //Error Handling part
        catch (LdapException lexc)
        {
            String error = lexc.ServerErrorMessage;
            string pp = error.Substring(76, 4);
            string ppp = pp.Trim();

            if ("52e" == ppp)
            {
                MessageBox.Show("Invalid Username or password, contact ADA Team");
            }
            if ("775​" == ppp)
            {
                MessageBox.Show("User account locked, contact ADA Team");
            }
            if ("525​" == ppp)
            {
                MessageBox.Show("User not found, contact ADA Team");
            }
            if ("530" == ppp)
            {
                MessageBox.Show("Not permitted to logon at this time, contact ADA Team");
            }
            if ("531" == ppp)
            {
                MessageBox.Show("Not permitted to logon at this workstation, contact ADA Team");
            }
            if ("532" == ppp)
            {
                MessageBox.Show("Password expired, contact ADA Team");
            }
            if ("533​" == ppp)
            {
                MessageBox.Show("Account disabled, contact ADA Team");
            }
            if ("533​" == ppp)
            {
                MessageBox.Show("Account disabled, contact ADA Team");
            }



        } //common error handling
        catch (Exception exc)
        {
            MessageBox.Show("Invalid Username or password, contact ADA Team");

        }

        finally {
            tbUID.Text = "";
            tbPass.Text = "";

        }
    }
Gayan Chinthaka Dharmarathna
sumber