2010-09-30 13 views
13

तो जैसे कोड का उपयोग कर किसी अन्य उपयोगकर्ता,.NET प्रतिरूपण लॉगऑन थ्रेड-सुरक्षित है?

[DllImport("advapi32.dll", SetLastError = true)] 

private static extern bool 

LogonUser(string lpszUsername, string lpszDomain, 
      string lpszPassword, int dwLogonType, 
      int dwLogonProvider, ref IntPtr phToken); 
var handle = IntPtr.Zero; 

const int LOGON32_LOGON_NETWORK = 3; 
const int LOGON32_PROVIDER_DEFAULT = 0; 
const int SecurityImpersonation = 2; 
LogonUser(username, domain, 
      password, LOGON32_LOGON_NETWORK, 
      LOGON32_PROVIDER_DEFAULT, ref handle)) 

दो विभिन्न समवर्ती धागे पर प्रतिरूपित करने के लिए, वे एक दूसरे के साथ हस्तक्षेप करेगा निम्नलिखित? यानी, क्या वर्तमान में लॉग-ऑन उपयोगकर्ता थ्रेड से जुड़ा हुआ है, या मेजबान प्रक्रिया के साथ?

मैं एक विंडोज़ इम्पर्सनेशन कॉन्टेक्स्ट ऑब्जेक्ट बनाने के लिए लॉगऑन हैंडल का उपयोग कर रहा हूं, जिसे एक निजी राज्य क्षेत्र के रूप में "इंपर्सोनेटर" (नीचे कोड) नाम दिया गया है। इसलिए, चूंकि यह WindowsImpersonationContext ऑब्जेक्ट इस प्रकार के उदाहरण में एक स्थानीय निजी फ़ील्ड है, और प्रत्येक बार जब मैं क्रेडेंशियल के कुछ सेट का प्रतिरूपण करना चाहता हूं, तो इस प्रकार का एक नया उदाहरण बनाया गया है, मैं मान सकता हूं कि यह WindowsImpersonationContext का उपयोग किया जा रहा है

किसी भी सार्वजनिक स्थैतिक (विजुअल बेसिक में साझा): एक जैसे

using (Impersonator.Impersonate(userId, domain, password)) 
    { 
     // Code I want to execute using supplied credentials 
    } 

क्या मुझे चिंतित है MSDN पेज WindowsImpersonationContext कि कहते हैं पर बयान है ब्लॉक के भीतर कोड के निष्पादन के दौरान सभी एसीएल सत्यापन प्रदर्शन इस प्रकार के सदस्य धागे सुरक्षित हैं। किसी भी इंस्टेंस सदस्यों को थ्रेड सुरक्षित होने की गारंटी नहीं है।

Impersonator वर्ग:

public class Impersonator: IDisposable 
{ 
    #region Declarations 
     private readonly string username; 
     private readonly string password; 
     private readonly string domain; 

     // This will hold the security context 
     // for reverting back to the client after 
     // impersonation operations are complete 
     private WindowsImpersonationContext impersonationContext; 
    #endregion Declarations 

    #region Constructors 

     public Impersonator(string UserName, 
      string Domain, string Password) 
     { 
      username = UserName; 
      domain = Domain; 
      password = Password; 
     } 
    #endregion Constructors 

    #region Public Methods 
     public static Impersonator Impersonate(
      string userName, string domain, string password) 
     { 
      var imp = new Impersonator(userName, domain, password); 
      imp.Impersonate(); 
      return imp; 
     } 

     public void Impersonate() 
     { 
      impersonationContext = Logon().Impersonate(); 
     } 

     public void Undo() { 
      impersonationContext.Undo(); 
     } 
    #endregion Public Methods 

    #region Private Methods 
     private WindowsIdentity Logon() 
     { 
      var handle = IntPtr.Zero; 

      const int LOGON32_LOGON_NETWORK = 3; 
      const int LOGON32_PROVIDER_DEFAULT = 0; 
      const int SecurityImpersonation = 2; 

      // Attempt to authenticate domain user account 
      try 
      { 
       if (!LogonUser(username, domain, 
        password, LOGON32_LOGON_NETWORK, 
        LOGON32_PROVIDER_DEFAULT, ref handle)) 
        throw new LogonException(
         "User logon failed. Error Number: " + 
         Marshal.GetLastWin32Error()); 

       // ---------------------------------- 
       var dupHandle = IntPtr.Zero; 
       if (!DuplicateToken(handle, 
        SecurityImpersonation, 
        ref dupHandle)) 
        throw new LogonException(
         "Logon failed attemting to duplicate handle"); 

       // Logon Succeeded ! return new WindowsIdentity instance 
       return (new WindowsIdentity(handle)); 
      } 
      // Close the open handle to the authenticated account 
      finally { CloseHandle(handle); } 
     } 

     #region external Win32 API functions 
      [DllImport("advapi32.dll", SetLastError = true)] 
      private static extern bool 
       LogonUser(string lpszUsername, string lpszDomain, 
         string lpszPassword, int dwLogonType, 
         int dwLogonProvider, ref IntPtr phToken); 

      [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
      private static extern bool CloseHandle(IntPtr handle); 
      // -------------------------------------------- 

      [DllImport("advapi32.dll", CharSet = CharSet.Auto, 
       SetLastError = true)] 
      public static extern bool DuplicateToken(
       IntPtr ExistingTokenHandle, 
       int SECURITY_IMPERSONATION_LEVEL, 
       ref IntPtr DuplicateTokenHandle); 
      // -------------------------------------------- 
     #endregion external Win32 API functions 
    #endregion Private Methods 

    #region IDisposable 
     private bool disposed; 

     public void Dispose() { Dispose(true); } 

     public void Dispose(bool isDisposing) 
     { 
      if (disposed) 
       return; 
      if (isDisposing) 
       Undo(); 
      // ----------------- 
      disposed = true; 
      GC.SuppressFinalize(this); 
     } 

     ~Impersonator() { 
      Dispose(false); 
     } 

    #endregion IDisposable 
} 

उत्तर

4

यह कुछ भी से संबद्ध नहीं है। आपके पास हैंडल एक लॉगऑन हैंडल है। एक बार आपके पास यह हो जाने के बाद, आप उस हैंडल का उपयोग थ्रेड पर उपयोगकर्ता को प्रतिरूपण करने के लिए करते हैं (WindowsIdentity.Impersonate पर कॉल करके) या किसी प्रक्रिया के लिए (या तो CreateProcess API function के माध्यम से या थ्रेड पर प्रतिरूपण करके और फिर उपयोगकर्ता का प्रतिरूपण करते समय एक नया Process उदाहरण बनाकर)।

किसी भी तरह से, LogonUser API function पर कॉल करने से कोई भी प्रतिरूपण नहीं होता है, यह आपको केवल एक उपयोगकर्ता हैंडल देता है जिसे आपको प्रतिरूपण करने की आवश्यकता होती है (मान लीजिए कि आपको विशेषाधिकार है)।

+0

ठीक है, मैं एक विंडोज़ इम्पर्सनेशन कॉन्टेक्स्ट ऑब्जेक्ट बनाने के लिए उस हैंडल का उपयोग करता हूं, जो थ्रेड-सुरक्षित है, (यह प्रति उपयोग किए गए परिभाषित प्रकार का एक उदाहरण है)। "जुड़े" से, मेरा मतलब था कि लॉगऑन हैंडल कहां संग्रहीत है? जैसा कि मैं इसे समझता हूं, यह WindowsImpersonationContext ऑब्जेक्ट है जो सुरक्षा संदर्भ के संदर्भ में "रखता है", और यदि यह थ्रेड में साझा नहीं किया गया है तो मुझे ठीक होना चाहिए ... सही? –

+0

मुझे एमएसडीएन पेज http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx पर बयान क्या है, जो कहता है: "कोई भी सार्वजनिक स्थैतिक (विजुअल बेसिक में साझा) इस प्रकार के सदस्य थ्रेड सुरक्षित हैं। किसी भी इंस्टेंस सदस्यों को थ्रेड सुरक्षित होने की गारंटी नहीं है। " –

+0

@ चार्ल्स ब्रेटाना: WindowsImpersonationContext इंस्टेंस के इंस्टेंस सदस्य थ्रेड-सुरक्षित नहीं हैं। आप गारंटीकृत सुरक्षा के साथ कई धागे से एक ही उदाहरण में कॉल नहीं कर सकते हैं। यह ऑब्जेक्ट .NET में अधिकांश लोगों की तरह है, उदाहरण के सदस्य थ्रेड-सुरक्षित नहीं हैं, स्थिर सदस्य हैं। जहां लॉग इन हैंडल संग्रहीत किया जाता है, हैंडल इंटिप्ट में है, जो लॉगिन टोकन के लिए जानकारी को इंगित करता है। – casperOne

1

मुझे लगता है कि आपका मतलब है: "यदि थ्रेड ए जो का प्रतिरूपण करता है और साथ ही थ्रेड बी फ्रेड का प्रतिरूपण करता है तो यह सब ठीक काम करेगा।"

आईई। धागा एक जो के रूप में काम करेगा (और फ्रेड नहीं) और इसके विपरीत। इसका जवाब है हाँ; प्रतिरूपण धागे से संबंधित है।

संबंधित मुद्दे