2010-09-30 27 views
13

Nếu sử dụng mã như sau để mạo danh người dùng khác,.NET có phải là trình duyệt đăng nhập an toàn chủ đề không?

[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)) 

trên hai luồng đồng thời khác nhau, họ sẽ can thiệp với nhau? Tức là, hiện tại người dùng đã đăng nhập có được liên kết với luồng hay với quy trình lưu trữ không?

Tôi đang sử dụng trình quản lý đăng nhập để tạo đối tượng WindowsImpersonationContext, dưới dạng trường trạng thái riêng tư trong một phiên bản của loại tôi đặt tên là "Trình mạo danh" (mã bên dưới). Vì vậy, vì đối tượng WindowsImpersonationContext này là một trường private cục bộ trong một thể hiện kiểu này, và một cá thể mới của kiểu này được tạo ra mỗi khi tôi muốn mạo danh một số thông tin xác thực, tôi có thể giả định rằng WindowsImpersonationContext này là những gì đang được sử dụng để thực hiện tất cả kiểm chứng thực ACL trong thực thi mã trong một khối như

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

gì có tôi quan tâm là tuyên bố trên MSDN trang WindowsImpersonationContext nói rằng:

Bất kỳ public static (chung trong Visual Basic) các thành viên thuộc loại này là chủ đề an toàn. Bất kỳ thành viên cá thể nào cũng không được bảo đảm là luồng an toàn.

Impersonator lớp:

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 
} 

Trả lời

4

Nó không liên quan đến bất cứ điều gì. Các xử lý mà bạn có là một xử lý đăng nhập. Một khi bạn có điều đó, bạn sử dụng tay cầm đó để mạo danh người dùng trên một chuỗi (bằng cách gọi WindowsIdentity.Impersonate) hoặc cho một quá trình (hoặc thông qua CreateProcess API function hoặc bằng cách mạo danh trên luồng và sau đó tạo một phiên bản Process mới trong khi mạo danh người dùng).

Dù bằng cách nào, gọi LogonUser API function không thực hiện bất kỳ mạo danh nào, nó chỉ cung cấp cho bạn một xử lý người dùng cần thực hiện mạo danh (giả sử rằng bạn có đặc quyền).

+0

Phải, tôi sử dụng tay cầm đó để tạo một đối tượng WindowsImpersonationContext, đó là chủ đề an toàn IS, (nó là một thể hiện của một kiểu xác định được tạo ra một lần cho mỗi lần sử dụng). Bởi "liên quan", tôi có nghĩa là nơi xử lý đăng nhập được lưu trữ? Khi tôi hiểu nó, nó là đối tượng WindowsImpersonationContext này "giữ" tham chiếu đến bối cảnh bảo mật, và nếu điều này không được chia sẻ qua các chủ đề tôi nên được ok ... phải không? –

+0

Điều gì khiến tôi lo ngại là tuyên bố trên trang msdn http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx có nội dung: "Bất kỳ tĩnh công cộng nào (Được chia sẻ trong Visual Basic) các thành viên thuộc loại này là an toàn chủ đề. Bất kỳ thành viên nào cũng không được bảo đảm là luồng an toàn. " –

+0

@Charles Bretana: Các cá thể thành viên của cá thể WindowsImpersonationContext KHÔNG phải là chủ đề an toàn. Bạn không thể thực hiện cuộc gọi đến cùng một phiên bản từ nhiều luồng với bảo đảm an toàn. Đối tượng này cũng giống như hầu hết các đối tượng khác trong .NET, các thành viên instance không phải là thread-safe, các thành viên tĩnh là. Đối với nơi lưu trữ đăng nhập, bộ điều khiển nằm trong IntPtr, trỏ đến thông tin cho mã thông báo đăng nhập. – casperOne

1

Tôi nghĩ bạn có nghĩa là: "Nếu chuỗi A mạo danh Joe và đồng thời chuỗi B mạo danh Fred, tất cả sẽ hoạt động OK".

I.e. sẽ đề một tác phẩm như Joe (chứ không phải Fred) và ngược lại. Câu trả lời là có; mạo danh thuộc về chủ đề.

Các vấn đề liên quan