एक्टिव डायरेक्ट्री के खिलाफ यूजरनेम और पासवर्ड को मान्य करें?


526

मैं सक्रिय निर्देशिका के खिलाफ उपयोगकर्ता नाम और पासवर्ड कैसे मान्य कर सकता हूं? मैं बस यह जांचना चाहता हूं कि उपयोगकर्ता नाम और पासवर्ड सही है या नहीं।

जवाबों:


642

यदि आप .NET 3.5 या नए पर काम करते हैं, तो आप System.DirectoryServices.AccountManagementनेमस्पेस का उपयोग कर सकते हैं और अपनी साख को आसानी से सत्यापित कर सकते हैं:

// 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");
}

यह सरल है, यह विश्वसनीय है, यह आपके अंत में 100% C # प्रबंधित कोड है - आप इससे अधिक क्या मांग सकते हैं? :-)

इसके बारे में सब कुछ यहां पढ़ें:

अपडेट करें:

जैसा कि इस अन्य SO प्रश्न (और इसके उत्तर) में उल्लिखित है , इस कॉल के साथ एक समस्या है जो संभवतः Trueकिसी उपयोगकर्ता के पुराने पासवर्ड के लिए वापस आ रही है । बस इस व्यवहार के बारे में पता होना चाहिए और अगर ऐसा होता है तो बहुत आश्चर्यचकित मत होइए :-) (@MikeGledhill को यह इंगित करने के लिए धन्यवाद!)


36
अपने डोमेन में, मुझे pc.ValidateCredentials ("myuser", "mypassword", ContextOptions.Negotiate) या मुझे निर्दिष्ट करना था।
एलेक्स पेक

12
यदि पासवर्ड की समय सीमा समाप्त हो गई है या खाते अक्षम हैं, तो ValidateCredentials गलत वापस आ जाएंगे। दुर्भाग्य से, यह आपको नहीं बताता है कि यह गलत क्यों लौटा है (जो एक दया है क्योंकि इसका मतलब है कि मैं कुछ समझदार नहीं कर सकता जैसे उपयोगकर्ता अपना पासवर्ड बदलने के लिए पुनर्निर्देशित करता है)।
क्रिस जे

64
'अतिथि' खाते से भी सावधान रहें - यदि डोमेन-स्तरीय अतिथि खाता सक्षम है, तो यदि आप इसे गैर-मौजूद उपयोगकर्ता देते हैं, तो ValidateCredentials सही है । नतीजतन, आप यह देखने के लिए कॉल कर सकते हैं कि UserPrinciple.FindByIdentityक्या पहले यूजर आईडी में पास मौजूद है।
क्रिस जे

7
@AlexPeck: यही कारण है कि आपको ऐसा करना पड़ा (मेरे जैसा) यह था कि .NET डिफ़ॉल्ट रूप से निम्नलिखित तकनीकों का उपयोग करता है: LDAP + SSL, Kerberos, फिर RPC। मुझे संदेह है कि RPC आपके नेटवर्क (अच्छा!) में बंद है और Kerberos वास्तव में .NET द्वारा उपयोग नहीं किया जाता है जब तक कि आप स्पष्ट रूप से इसका उपयोग नहीं करते हैं ContextOptions.Negotiate
ब्रेट वेनेस्ट्रा

5
ध्यान रखें कि यदि उपयोगकर्ता अपने सक्रिय निर्देशिका पासवर्ड को बदल देता है, तो कोड का यह टुकड़ा उपयोगकर्ता को अपने पुराने पासवर्ड का उपयोग करके खुशी से प्रमाणित करना जारी रखेगा। हाँ, वास्तव में। यहाँ पढ़ें: stackoverflow.com/questions/8949501/…
माइक Gledhill

70

हम अपने इंट्रानेट पर ऐसा करते हैं

आपको System.DirectoryServices का उपयोग करना होगा;

यहाँ कोड की हिम्मत कर रहे हैं

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();
        }
    }
}

9
आप "पथ" में क्या डालते हैं? डोमेन का नाम? सर्वर का नाम? डोमेन के लिए LDAP पथ? सर्वर के लिए LDAP पथ?
इयान बॉयड 15

3
उत्तर 1: नहीं, हम इसे एक वेब सेवा के रूप में चलाते हैं, इसलिए इसे मुख्य वेब ऐप में कई स्थानों से कॉल किया जा सकता है। उत्तर 2: पथ में LDAP जानकारी शामिल है ... LDAP: // DC = domainname1, DC = domainname2, DC = com
भोजनप्राप्तक

3
ऐसा लगता है कि यह LDAP इंजेक्शन की अनुमति दे सकता है। आप strAccountId में किसी भी कोष्ठक से बचना या निकालना सुनिश्चित कर सकते हैं
Brain2000

इसका मतलब यह है कि strPasswordसादे पाठ में LDAP में संग्रहीत किया जाता है?
मैट कोकाज

15
चर Close()पर स्पष्ट रूप से कॉल करने की आवश्यकता नहीं होनी चाहिए using
Nyerguds

62

यहां प्रस्तुत कई समाधानों में एक गलत उपयोगकर्ता / पासवर्ड और एक पासवर्ड के बीच अंतर करने की क्षमता का अभाव है, जिसे बदलना होगा। यह निम्नलिखित तरीके से किया जा सकता है:

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);
            }
        }
    }
}

यदि उपयोगकर्ता पासवर्ड गलत है, या उपयोगकर्ता मौजूद नहीं है, तो त्रुटि होगी

"8009030C: LdapErr: DSID-0C0904DC, टिप्पणी: AcceptSecurityContext त्रुटि, डेटा 52e, v1db1"

यदि उपयोगकर्ता पासवर्ड को बदलना होगा, तो उसमें शामिल होगा

"8009030C: LdapErr: DSID-0C0904DC, टिप्पणी: AcceptSecurityContext त्रुटि, डेटा 773, v1db1"

lexc.ServerErrorMessageडेटा मान Win32 त्रुटि कोड की एक हेक्स प्रतिनिधित्व है। ये वही त्रुटि कोड हैं, जो अन्यथा Win32 LogonUser API कॉल को लागू करके वापस कर दिए जाएंगे। नीचे दी गई सूची में हेक्स और दशमलव मानों के साथ सामान्य मूल्यों की एक श्रृंखला है:

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)

2
दुर्भाग्य से, कुछ AD स्थापना LDAP उप त्रुटि कोड वापस नहीं करती हैं, जिसका अर्थ है कि यह समाधान काम नहीं करेगा।
सोरेन मोर्स

4
परियोजना के लिए कुछ संदर्भ जोड़ना न भूलें: System.DirectoryServicesऔरSystem.DirectoryServices.Protocols
टॉमएक्सपी ४११

3
मेरा प्रश्न, हालाँकि, यह है: आपको LDAP सर्वर नाम कैसे मिलता है? यदि आप एक पोर्टेबल एप्लिकेशन लिख रहे हैं, तो आप उपयोगकर्ता से प्रत्येक नेटवर्क पर AD सर्वर के नाम को जानने या आपूर्ति करने की अपेक्षा नहीं कर सकते।
टॉमएक्सपी 411 22

1
मेरे पास ऐसे उपयोगकर्ता हैं जो विशिष्ट कार्यस्थानों में प्रवेश करने के लिए प्रतिबंधित हैं; मैं उस कार्य केंद्र को कैसे निर्दिष्ट करूं, जिसके लिए मैं लॉगिन की कोशिश कर रहा हूं? (वर्कस्टेशन 1 डेटा 531 के साथ विफल हो जाएगा, वर्कस्टेशन 2 ठीक काम करेगा, उदाहरण के लिए)
akohlsmith

1
मुझे अजीब लगता है क्योंकि मुझे नहीं लगता कि आपको पर्याप्त क्रेडिट मिल रहा है। यह Win32 API कॉल की परेशानी के बिना पूरी तरह से प्रबंधित विधि है यह निर्धारित करने के लिए कि "उपयोगकर्ता को पासवर्ड रीसेट करना होगा" जो स्पष्ट रूप से प्राप्त किए गए अन्य उत्तरों में से कोई भी नहीं है। क्या इस विधि में कोई खामी है, जिसके कारण इसकी सराहना की दर कम है? हम्म ...
लियोनेट चेन

34

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;
}

खराब उपयोगकर्ता / पासवर्ड का पता लगाने के लिए NativeObject एक्सेस आवश्यक है


4
यह कोड खराब है क्योंकि यह एक प्राधिकरण जांच भी कर रहा है (यह जांचें कि क्या उपयोगकर्ता को सक्रिय निर्देशिका जानकारी पढ़ने की अनुमति है)। उपयोगकर्ता नाम और पासवर्ड मान्य हो सकते हैं, लेकिन उपयोगकर्ता को जानकारी पढ़ने और अपवाद प्राप्त करने की अनुमति नहीं है। दूसरे शब्दों में, आपके पास एक मान्य उपयोगकर्ता नाम और पासवर्ड हो सकता है, लेकिन फिर भी एक अपवाद मिलता है।
इयान बॉयड

2
मैं वास्तव में मूल समकक्ष के लिए पूछने की प्रक्रिया में हूं PrincipleContext- जो केवल .NET 3.5 में मौजूद है। लेकिन अगर आप .NET 3.5 या नए का उपयोग कर रहे हैं, तो आपको उपयोग करना चाहिएPrincipleContext
इयान बॉयड

28

दुर्भाग्य से AD पर किसी उपयोगकर्ता क्रेडेंशियल्स की जांच करने का कोई "सरल" तरीका नहीं है।

अब तक प्रस्तुत हर विधि के साथ, आपको एक गलत-नकारात्मक मिल सकती है: एक उपयोगकर्ता का क्रेडिट मान्य होगा, हालांकि AD कुछ शर्तों के तहत गलत वापस आ जाएगा:

  • अगला लॉगऑन में पासवर्ड बदलने के लिए उपयोगकर्ता की आवश्यकता होती है।
  • उपयोगकर्ता का पासवर्ड समाप्त हो गया है।

ActiveDirectory आपको यह निर्धारित करने के लिए LDAP का उपयोग करने की अनुमति नहीं देगा कि क्या कोई पासवर्ड इस तथ्य के कारण अमान्य है कि उपयोगकर्ता को पासवर्ड बदलना होगा या यदि उनका पासवर्ड समाप्त हो गया है।

पासवर्ड परिवर्तन या पासवर्ड की समय सीमा समाप्त हो जाने के लिए, आप Win32: LogonUser () को कॉल कर सकते हैं, और निम्न 2 आवेदकों के लिए विंडो त्रुटि कोड की जांच कर सकते हैं:

  • ERROR_PASSWORD_MUST_CHANGE = 1907
  • ERROR_PASSWORD_EXPIRED = 1330

1
क्या मैं पूछ सकता हूं कि आपको अवसान और मुस्तैदी के लिए अवमूल्यन कहां मिला ... उन्हें कहीं नहीं मिला लेकिन यहां :)
mabstrei


धन्यवाद। मैं यह पता लगाने की कोशिश कर रहा था कि मेरी मान्यता हर समय झूठी साबित हो रही थी। ऐसा इसलिए था क्योंकि उपयोगकर्ता को अपना पासवर्ड बदलना होगा।
डेइस विसेंटिन

22

संभवत: सबसे आसान तरीका PInvoke LogonUser Win32 API.eg है

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

MSDN संदर्भ यहाँ ...

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

निश्चित रूप से लॉगऑन प्रकार का उपयोग करना चाहते हैं

LOGON32_LOGON_NETWORK (3)

यह केवल एक हल्के टोकन बनाता है - AuthN जाँच के लिए एकदम सही। (अन्य प्रकार का उपयोग इंटरेक्टिव सत्रों के निर्माण के लिए किया जा सकता है)


जैसा कि @Alan बताते हैं, LogonUser API में System.DirectoryServices कॉल से परे कई उपयोगी लक्षण हैं।
Stephbu

3
@cciotti: नहीं, यह गलत है। किसी को सही ढंग से प्रमाणित करने का सबसे अच्छा तरीका है लॉगऑनसर्पी का उपयोग @stephbu लिखना। इस पोस्ट में वर्णित अन्य सभी विधियां 100% काम नहीं करेंगी। बस एक नोट हालांकि, मेरा मानना ​​है कि आपको लॉगऑनसर को कॉल करने के लिए डोमेन में शामिल होना होगा।
एलन

@ क्रेडेंशियल जेनरेट करने के लिए आपको एक मान्य डोमेन अकाउंट में डोमेन को कनेक्ट करने में सक्षम होना चाहिए। हालाँकि मुझे पूरा यकीन है कि आपकी मशीन को डोमेन का सदस्य होना जरूरी नहीं है।
Stephbu

2
LogonUserएपीआई के लिए उपयोगकर्ता की आवश्यकता अधिनियम ऑपरेटिंग सिस्टम के एक भाग के रूप privelage; ऐसा कुछ नहीं है जो उपयोगकर्ताओं को मिलता है - और ऐसा कुछ नहीं जिसे आप संगठन के प्रत्येक उपयोगकर्ता को देना चाहते हैं। ( msdn.microsoft.com/en-us/library/aa378184(v=vs.85).aspx )
इयान बॉयड

1
LogonUser को केवल Windows 2000 के लिए ऑपरेटिंग सिस्टम के हिस्से के रूप में और support.microsoft.com/kb/180548 के अनुसार अधिनियम की आवश्यकता है ... यह सर्वर 2003 और उच्चतर के लिए साफ दिखता है।
क्रिस जे

18

एक पूर्ण .नेट समाधान, System.DirectoryServices नाम स्थान से कक्षाओं का उपयोग करना है। वे एक AD सर्वर को सीधे क्वेरी करने की अनुमति देते हैं। यहाँ एक छोटा सा नमूना है जो यह करेगा:

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

यह कोड प्रदान किए गए क्रेडेंशियल्स का उपयोग करके सीधे AD सर्वर से जुड़ता है। यदि क्रेडेंशियल अमान्य हैं, तो खोजकर्ता। FindOne () एक अपवाद को फेंक देगा। ErrorCode "अमान्य उपयोगकर्ता नाम / पासवर्ड" COM त्रुटि के अनुरूप है।

आपको AD उपयोगकर्ता के रूप में कोड चलाने की आवश्यकता नहीं है। वास्तव में, मैं succesfully डोमेन के बाहर एक ग्राहक से एक AD सर्वर पर informations को क्वेरी करने के लिए इसका इस्तेमाल करते हैं!


प्रमाणीकरण प्रकारों के बारे में कैसे? मुझे लगता है कि आप इसे अपने कोड में भूल गए। :-) डिफ़ॉल्ट निर्देशिका के द्वारा। सही। सुरक्षा सही पर सेट है? यह कोड उन LDAP पर काम नहीं करने वाला है जो सुरक्षित नहीं हैं (अनाम या कोई नहीं)। क्या मैं इसके साथ सही हूं?
जेरबसॉफ्ट

AD सर्वर को क्वेरी करने के लिए डाउन-साइड यह है कि आपके पास AD सर्वर को क्वेरी करने की अनुमति है। आपकी क्रेडेंशियल मान्य हो सकती है, लेकिन यदि आपके पास AD से क्वेरी करने की अनुमति नहीं है, तो आपको त्रुटि मिलेगी। यही कारण है कि तथाकथित फास्ट बिंद बनाया गया था; आप कुछ करने के लिए उपयोगकर्ता की क्षमता को अधिकृत किए बिना क्रेडेंशियल को मान्य करते हैं।
इयान बॉयड

2
यदि किसी व्यक्ति को क्रेडेंशियल्स की जाँच करने से पहले COMException को किसी अन्य कारण से फेंक दिया जाता है, तो क्या यह अनुमति नहीं देगा?
स्टीफन पॉल नैक

11

फिर भी एक और .NET कॉल LDAP क्रेडेंशियल्स को जल्दी से प्रमाणित करने के लिए है:

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

यह एकमात्र समाधान है जिसने मेरे लिए काम किया है, प्रिंसिपल कोटेक्स्ट का उपयोग करके मेरे लिए काम नहीं किया है।
डैनियल

PrincipalContext सुरक्षित LDAP कनेक्शन के लिए मान्य नहीं है (उर्फ LDAPS, जो पोर्ट 636 का उपयोग करता है
Kiquenet

10

इस कोड को आज़माएं (नोट: विंडोज सर्वर 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

सिवाय इसके कि आपको "लॉगऑनसेप्शन" के लिए अपना स्वयं का कस्टम अपवाद बनाना होगा


किसी विधि से जानकारी वापस करने के लिए अपवाद हैंडलिंग का उपयोग न करें। "अज्ञात उपयोगकर्ता नाम या खराब पासवर्ड" असाधारण नहीं है, यह लॉगऑनसर के लिए मानक व्यवहार है। बस झूठे लौटते हैं।
ट्रेब

हाँ ... यह एक पुराने VB6 पुस्तकालय से एक बंदरगाह था ... 2003 या तो लिखा है ... (जब। नेट पहली बार बाहर आया था)
चार्ल्स ब्रेटाना

यदि Windows 2000 पर चल रहा है, तो यह कोड काम नहीं करेगा ( support.microsoft.com/kb/180548 )
इयान बॉयड

1
इस पर पुनर्विचार करना। लॉगऑन उपयोगकर्ता का अपेक्षित व्यवहार, इसका उद्देश्य, उपयोगकर्ता को लॉग ऑन करना है । ऐसा लगता है कि कार्य करने के लिए विफल रहता है, यह है एक अपवाद। वास्तव में, विधि शून्य वापस आनी चाहिए, बूलियन नहीं। साथ ही, यदि आपने एक बूलियन लौटाया तो विधि के उपभोक्ता के पास उपयोगकर्ता को सूचित करने का कोई तरीका नहीं है कि विफलता का कारण क्या था।
चार्ल्स ब्रेटाना

5

यदि आप .NET 2.0 और प्रबंधित कोड के साथ फंस गए हैं, तो यहां एक और तरीका है जो स्थानीय और डोमेन खातों पर काम करता है:

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;
}   

मशीन के स्थानीय खातों के साथ अच्छी तरह से काम करता है वह स्क्रिप्ट लॉन्च करता है
eka808

BTW, इस विधि को सार्वजनिक स्थिर SecureString ToSecureString (स्ट्रिंग PwString) {char [] PasswordChars = PwString.ToCharArray () बनाने के लिए आवश्यक है; SecureString पासवर्ड = नया SecureString (); foreach (पासवर्ड सी में पासवर्ड) Password.AppendChar (c); ProcessStartInfo foo = new ProcessStartInfo (); foo.Password = पासवर्ड; वापसी foo.Password; }
eka808

इसके विपरीत, किसी को भी पासवर्ड के लिए SecureString का उपयोग करना चाहिए। WPF पासवर्डबॉक्स इसका समर्थन करता है।
स्टीफन ड्रू

5

विंडोज प्रमाणीकरण विभिन्न कारणों से विफल हो सकता है: एक गलत उपयोगकर्ता नाम या पासवर्ड, एक लॉक खाता, एक समाप्त पासवर्ड, और बहुत कुछ। इन त्रुटियों के बीच अंतर करने के लिए, LogonUser API फ़ंक्शन को P / Invoke के माध्यम से कॉल करें और फ़ंक्शन रिटर्न होने पर त्रुटि कोड की जांच करें 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()
    }
}

नमूना उपयोग:

try
{
    Win32Authentication.AuthenticateUser("EXAMPLE\\user", "P@ssw0rd");
    // Or: Win32Authentication.AuthenticateUser("user@example.com", "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;
    }
}

ध्यान दें: LogonUser आपके द्वारा मान्य डोमेन के साथ विश्वास संबंध की आवश्यकता है।


क्या आप बता सकते हैं कि आपका उत्तर उच्चतम मतदान वाले उत्तर से बेहतर क्यों है?
मोहम्मद अली

1
@ मोहम्मदअली: यदि आपको यह जानने की आवश्यकता है कि क्रेडेंशियल सत्यापन विफल क्यों हुआ (गलत क्रेडेंशियल्स, एक लॉक खाता, एक समाप्त पासवर्ड, आदि), तो लॉगऑनसर एपीआई फ़ंक्शन आपको बताएगा। इसके विपरीत, PrincipalContext.ValidateCredentials विधि (marc_s के उत्तर पर टिप्पणियों के अनुसार) नहीं होगी; यह इन सभी मामलों में गलत है। दूसरी ओर, LogonUser को डोमेन के साथ विश्वास संबंध की आवश्यकता होती है, लेकिन PrincipalContext.ValidateCredentials (मुझे लगता है) नहीं करता है।
माइकल लियू

2

मेरा सरल कार्य

 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;
        }
    }

1

यहाँ आपके संदर्भ के लिए मेरा पूर्ण प्रमाणीकरण समाधान है।

सबसे पहले, निम्नलिखित चार संदर्भों को जोड़ें

 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 = "";

        }
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.