2012-01-21 8 views
32

मैं सक्रिय निर्देशिका में उपयोगकर्ता के पासवर्ड को अद्यतन करने के लिए एक सरल समाधान पर काम कर रहा हूं।सक्रिय निर्देशिका अंतिम पासवर्ड क्यों मान्य करती है?

मैं उपयोगकर्ता पासवर्ड सफलतापूर्वक अपडेट कर सकता हूं। पासवर्ड अपडेट करना ठीक काम करता है।

using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain")) 
{ 
    // validate the credentials 
    bool isValid = pc.ValidateCredentials("myuser", "MyPass2"); 
} 

//returns true - which is good 

अब जब मैं कुछ गलत पासवर्ड यह बहुत अच्छी तरह से सत्यापित करता दर्ज करें: कहते हैं कि उपयोगकर्ता MyPass2

को MyPass1 से पासवर्ड को अपडेट किया गया अब जब मैं अपने कस्टम कोड को चलाने के उपयोगकर्ताओं का उपयोग कर credential को मान्य करने की सुविधा देता है:

using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain")) 
{ 
    // validate the credentials 
    bool isValid = pc.ValidateCredentials("myuser", "wrongPass"); 
} 

//returns false - which is good 

अब कुछ अजीब कारण के लिए, यह पिछले पिछले पासवर्ड जो था MyPass1 याद सत्यापित करता है?

using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "TheDomain")) 
{ 
    // validate the credentials 
    bool isValid = pc.ValidateCredentials("myuser", "MyPass1"); 
} 

//returns true - but why? we have updated password to Mypass2 

मैं इस कोड है:

Validate a username and password against Active Directory?

यह समाप्ति अंतिम पासवर्ड के साथ कुछ है या कि यह कैसे मान्यता चाहिए काम करने के लिए है?

+0

आपका डोमेन आधारभूत संरचना कितना बड़ा है? आप प्रत्येक बार एक अलग डीसी से कनेक्ट हो सकते हैं और नया पासवर्ड दोहराया नहीं गया है। –

+0

जब मैं एक नए पासवर्ड को अपडेट करता हूं, तो मैं पुराने पासवर्ड का उपयोग करके लॉगिन नहीं कर सकता। इसका एकमात्र जब मैं पुराने पासवर्ड :(लिए ValidateCredentials() विधि, अपने रिटर्न का उपयोग सही शायद कुछ कैश्ड क्रेडेंशियल्स के साथ करना है? – theITvideos

उत्तर

1

इसे चलाने के संदर्भ के आधार पर, इसे "cached credentials" नामक किसी चीज़ के साथ करना पड़ सकता है।

+0

अगर यह कैश्ड क्रेडेंशियल्स के साथ कुछ करने के लिए है ... मैं कैसे साफ कर सकते हैं सी # – theITvideos

45

कारण यह है कि आप इसे क्यों देख रहे हैं special behavior specific to NTLM network authentication के साथ करना है।

एक सुरक्षित LDAP सिलसिले में एक PrincipalContext उदाहरण परिणामों पर ValidateCredentials विधि बनाया जा रहा है कॉलिंग, एक बाँध आपरेशन के बाद एक ldap_bind_s समारोह कॉल का उपयोग कर कि कनेक्शन पर प्रदर्शन किया जा रहा है।

ValidateCredentials पर कॉल करते समय उपयोग की जाने वाली प्रमाणीकरण विधि AuthType.Negotiate है। इस परिणाम का उपयोग बाइंड ऑपरेशन में केर्बेरोस का उपयोग करने का प्रयास किया जा रहा है, जो कि एनटीएलएम नहीं है) ऊपर वर्णित विशेष व्यवहार को प्रदर्शित नहीं करेगा। हालांकि, केर्बेरोस का उपयोग करने का बाध्य प्रयास विफल हो जाएगा (पासवर्ड गलत है और सभी), जिसके परिणामस्वरूप एनटीएलएम का उपयोग करके एक और प्रयास किया जा सकेगा।

  1. माइक्रोसॉफ्ट KB लेख मैं छोटा या OldPasswordAllowedPeriod रजिस्ट्री मान का उपयोग कर एक पुराने पासवर्ड के जीवनकाल अवधि समाप्त करने के लिए जुड़ा हुआ में निर्देशों का पालन:

    आप इस दृष्टिकोण दो तरीके हैं। शायद सबसे आदर्श समाधान नहीं है।

  2. प्रमाण पत्र मान्य करने के लिए PrincipleContext कक्षा का उपयोग न करें। अब जब आप जानते हैं (लगभग) ValidateCredentials काम करता है, तो मैन्युअल रूप से प्रक्रिया को करने के लिए आपके लिए बहुत मुश्किल नहीं होना चाहिए। आप जो करना चाहते हैं वह एक नया एलडीएपी कनेक्शन (LdapConnection) बनाएं, अपने नेटवर्क प्रमाण-पत्र सेट करें, एथटाइप को स्पष्ट रूप से AuthType.Kerberos पर सेट करें, और फिर Bind() पर कॉल करें। यदि प्रमाण-पत्र खराब हैं तो आपको अपवाद मिलेगा।

निम्नलिखित कोड दिखाता है कि आप केवल केर्बेरोस का उपयोग करके प्रमाणिक सत्यापन कैसे कर सकते हैं। उपयोग में प्रमाणीकरण विधि विफलता की स्थिति में एनटीएलएम पर वापस नहीं आ जाएगी।

private const int ERROR_LOGON_FAILURE = 0x31; 

private bool ValidateCredentials(string username, string password, string domain) 
{ 
    NetworkCredential credentials 
    = new NetworkCredential(username, password, domain); 

    LdapDirectoryIdentifier id = new LdapDirectoryIdentifier(domain); 

    using (LdapConnection connection = new LdapConnection(id, credentials, AuthType.Kerberos)) 
    { 
    connection.SessionOptions.Sealing = true; 
    connection.SessionOptions.Signing = true; 

    try 
    { 
     connection.Bind(); 
    } 
    catch (LdapException lEx) 
    { 
     if (ERROR_LOGON_FAILURE == lEx.ErrorCode) 
     { 
     return false; 
     } 
     throw; 
    } 
    } 
    return true; 
} 

मैं अपने कोड के प्रवाह नियंत्रण को संभालने के लिए कभी भी अपवादों का उपयोग करने की कोशिश नहीं करता; हालांकि, इस विशेष उदाहरण में, एलडीएपी कनेक्शन पर प्रमाण-पत्रों का परीक्षण करने का एकमात्र तरीका एक बाइंड ऑपरेशन का प्रयास करना प्रतीत होता है, जो प्रमाण-पत्र खराब होने पर अपवाद फेंक देगा। PrincipalContext एक ही दृष्टिकोण लेता है।

+0

के माध्यम से पासवर्ड कैश आपके उत्तर के लिए धन्यवाद। मेरे पास 2 दृष्टिकोणों के बारे में दो प्रश्न हैं। – theITvideos

+0

1) क्या रजिस्ट्री को छूए बिना सी # या डायरेक्टिव डायरेक्टरी आईडीई के माध्यम से 'OldPasswordAllowedPeriod' अपडेट करना संभव है? 2) तो माइक्रोसॉफ्ट आलेख के मुताबिक, OldPasswordAllowedPeriod के लिए मिनटों में डिफ़ॉल्ट समय 60 मिनट है ... क्या इसकी पुष्टि करने के लिए सक्रिय निर्देशिका में कोई तरीका है। 3) क्या आप एक सी # कोड सुझा सकते हैं जो उपयोगकर्ता को AuthType.Kerberos विधि का उपयोग करके मान्य करता है। उपयोगकर्ता नाम और पासवर्ड पैरामीटर लेना। कृपया उत्तर दें। – theITvideos

+0

मैंने कुछ नमूना कोड जोड़ा। मुझे मानक रजिस्ट्री API का उपयोग करने के बाहर 'OldPasswordAllowedPeriod' रजिस्ट्री मान सेट करने के किसी भी तरीके से अवगत नहीं है। –

1

मुझे केवल उपयोगकर्ता के वर्तमान प्रमाण-पत्रों को सत्यापित करने का कोई तरीका मिला है। यह इस तथ्य को लेता है कि ChangePassword कैश किए गए क्रेडेंशियल्स का उपयोग नहीं करता है। पासवर्ड को इसके वर्तमान मान में बदलने का प्रयास करके, जो पहले पासवर्ड को मान्य करता है, हम यह निर्धारित कर सकते हैं कि पासवर्ड गलत है या कोई नीति समस्या है (दो बार एक ही पासवर्ड का पुन: उपयोग नहीं कर सकता)।

नोट: यह शायद तभी काम करेगा यदि आपकी पॉलिसी में कम से कम पासवर्ड दोहराने की अनुमति नहीं है।

 var isPasswordValid = PrincipalContext.ValidateCredentials(
      userName, 
      password); 

     // use ChangePassword to test credentials as it doesn't use caching, unlike ValidateCredentials 
     if (isPasswordValid) 
     { 
      try 
      { 
       user.ChangePassword(password, password); 
      } 
      catch (PasswordException ex) 
      { 
       if (ex.InnerException != null && ex.InnerException.HResult == -2147024810) 
       { 
        // Password is wrong - must be using a cached password 
        isPasswordValid = false; 
       } 
       else 
       { 
        // Password policy problem - this is expected, as we can't change a password to itself for history reasons  
       } 
      } 
      catch (Exception) 
      { 
       // ignored, we only want to check wrong password. Other AD related exceptions should occure in ValidateCredentials 
      } 
     } 
संबंधित मुद्दे