2011-09-30 37 views
11

Tôi đang sử dụng một cái gì đó giống như các phương pháp sau đây để mạo danh một người dùng trong mã của tôi:Bắt tên người dùng hiện tại khi mạo nhận

How do you do Impersonation in .NET?

Trong lớp khác, tôi cần phải tìm hiểu người dùng hiện thời (như "mydomain \ moose "), nhưng tôi sẽ không có bất kỳ ý tưởng nào nếu tôi hiện đang mạo danh người dùng khác hay không.

Làm cách nào để nhận tên người dùng, nếu tôi đang mạo danh ai đó?

System.Environment.UserName and System.Security.Principal.WindowsIdentity.GetCurrent(). Đặt tên cho cả người dùng ban đầu, chứ không phải người dùng hiện đang mạo danh.

Xem chi tiết:

Tôi đang làm mạo danh này để tôi có thể truy cập vào một số tập tin trong một phần netowrk người dùng thường không có quyền truy cập vào.

Nếu tôi sử dụng loại đăng nhập LOGON32_LOGON_INTERACTIVE, tôi sẽ thấy người dùng mới, nhưng tôi không thể truy cập chia sẻ mạng. Nếu tôi sử dụng loại đăng nhập LOGON32_LOGON_NEW_CREDENTIALS (giá trị là 9), tôi có thể truy cập vào mạng chia sẻ nhưng tôi không thấy người dùng mới trong Environment.UserName.

+2

Nó phải trả lại người dùng bị mạo danh. Bạn có chắc chắn rằng bạn đang mạo danh trong cuộc gọi phương thức mà bạn tra cứu người dùng hiện tại không? – mellamokb

+0

Tôi vừa thử nghiệm bằng cách sử dụng người dùng giả mạo để truy cập vào thư mục mà người dùng đã đăng nhập của tôi không có quyền truy cập. Tôi có thể truy cập vào thư mục, nhưng cả hai phương thức vẫn trả về người dùng ban đầu. một khi tôi ngừng mạo danh, tôi bị truy cập từ chối truy cập vào thư mục, vì vậy tôi biết nó đang mạo danh một cách chính xác. – Moose

+0

Đã thêm chi tiết. Dường như là loại đăng nhập gây ra vấn đề. – Moose

Trả lời

18

BEGIN EDIT: Tôi đã nhận ra rằng nỗ lực đầu tiên của tôi để trả lời câu hỏi không rõ ràng. Vì vậy, tôi muốn bắt đầu một nỗ lực:

Trước tiên, tôi muốn chỉ ra những gì thuộc tính WindowsIdentity.GetCurrent().Name sẽ trở lại nếu bạn sử dụng LOGON32_LOGON_NEW_CREDENTIALS hoặc LOGON32_LOGON_INTERACTIVE as type đăng nhập cho LogonUser (bên trong lớp mạo danh) chức năng:

  1. Sử dụng LOGON32_LOGON_INTERACTIVE

    // Assuming this code runs under USER_B 
    
    using (var imp = new Impersonation("treyresearch", "USER_A", "SecurePwd", LOGON32_LOGON_INTERACTIVE)) 
    { 
        // Now, we run under USER_A 
        Console.Out.WriteLine(WindowsIdentity.GetCurrent().Name); // Will return USER_A 
    } 
    
  2. Sử dụng LOGON32_LOGON_NEW_CREDENTIALS

    // Assuming this codes runs under USER_B 
    
    using (var imp = new Impersonation("treyresearch", "USER_A", "SecurePwd", LOGON32_LOGON_NEW_CREDENTIALS)) 
    { 
        Console.Out.WriteLine(WindowsIdentity.GetCurrent().Name); // Will return USER_B 
    } 
    

Đây là hành vi như bạn đã mô tả trong câu hỏi của bạn và phù hợp với mô tả trên MSDN cho LogonUser chức năng. Đối với LOGON32_LOGON_NEW_CREDENTIALS mã thông báo người dùng được tạo chỉ là bản sao của mã thông báo người dùng hiện tại. Điều này có nghĩa là phiên người dùng đã tạo có cùng số nhận dạng làm chuỗi cuộc gọi. Các thông tin đăng nhập được chuyển đến chức năng LogonUser chỉ được sử dụng cho các kết nối mạng đi.

Thứ hai, hãy để tôi chỉ ra hai tình huống mà sự khác biệt được mô tả giữa LOGON32_LOGON_INTERACTIVELOGON32_LOGON_NEW_CREDENTIALS trở nên rõ ràng:

  • Hai miền tham gia máy tính: computer_A, computer_B
  • Hai người sử dụng: user_A (quản trị cục bộ trên computer_A) , user_B (chỉ các quyền người dùng chuẩn trên B)
  • Một networkshare trên computer_B (mynetworkshare, user_B không có quyền truy cập vào phần chia sẻ).
  • Một thư mục cục bộ trên máy tính_A (chỉ người dùng_A được phép ghi vào thư mục này).

Bạn chạy chương trình của mình trên máy tính_A (trong tài khoản của user_A). Bạn mạo danh user_B (sử dụng LOGON32_LOGON_INTERACTIVE). Sau đó, bạn kết nối với mạng chia sẻ trên computer_B và cố gắng sao chép một tập tin vào thư mục địa phương (chỉ user_A có quyền ghi vào thư mục này). Sau đó, bạn nhận được một thông báo lỗi bị từ chối truy cập, bởi vì thao tác tệp được thực hiện với quyền của user_B mà không có quyền đối với thư mục cục bộ.

Tình huống tương tự như trên. Nhưng bây giờ, chúng tôi sử dụng LOGON32_LOGON_NEW_CREDENTIALS để mạo danh user_B. Chúng tôi kết nối với ổ đĩa mạng và sao chép một tập tin từ ổ đĩa mạng vào thư mục cục bộ. Trong trường hợp này hoạt động thành công vì thao tác tệp được thực hiện với quyền của user_A.

END EDIT

Hope, điều này sẽ giúp.

+0

Điều này giúp ích. Thật không may, phương pháp duy nhất giúp tôi truy cập vào mạng chia sẻ tôi cần là bằng cách sử dụng LOGON32_LOGON_NEW_CREDENTIALS, nhưng sau đó tôi không thể nhìn thấy tôi là ai. Vì vậy, tôi sẽ cần phải cố gắng không sử dụng mạo danh trong trường hợp cụ thể này, mà tôi nghĩ là giải pháp thực sự anyway. Tôi đánh dấu câu trả lời này là câu trả lời vì nó có chi tiết nhất về sự khác biệt trong kiểu Logon được chuyển tới LogonUser(). – Moose

+0

@Moose: Nếu bạn chỉ cần biết thời tiết hay không bạn đang mạo danh thì hãy xem câu hỏi/câu trả lời stackoverflow sau đây: http://stackoverflow.com/questions/3973982/how-to-tell-if-current- thread-is-impersonating – Hans

+0

Tôi chỉ cần biết làm thế nào để có được danh tính người dùng và điều này đã cho tôi chính xác những gì tôi đang tìm kiếm. TUYỆT VỜI! –

5

Theo ví dụ tại http://msdn.microsoft.com/en-us/library/chf6fbt4.aspx các thay đổi nhận dạng hiện tại trong quá trình mạo danh. Bạn có chắc chắn mã của mình nằm trong khối mã bị mạo danh không?

+0

Có, chỉ cần kiểm tra. Vẫn không có may mắn. Tôi biết tôi đang bị mạo danh, nhưng nó vẫn mang lại người dùng ban đầu. – Moose

1
+0

Bạn có nghĩa là GetTokenInformation? Không chắc chắn rằng thậm chí có thể nhận CredHandle để cấp cho QueryCredentialAttributes do mã thông báo mạo danh HANDLE được trả lại từ LogonUser. –

2

Tôi đã viết một lớp helper nào đó:

public static class ImpersonationUtils 
{ 
    private const int SW_SHOW = 5; 
    private const int TOKEN_QUERY = 0x0008; 
    private const int TOKEN_DUPLICATE = 0x0002; 
    private const int TOKEN_ASSIGN_PRIMARY = 0x0001; 
    private const int STARTF_USESHOWWINDOW = 0x00000001; 
    private const int STARTF_FORCEONFEEDBACK = 0x00000040; 
    private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400; 
    private const int TOKEN_IMPERSONATE = 0x0004; 
    private const int TOKEN_QUERY_SOURCE = 0x0010; 
    private const int TOKEN_ADJUST_PRIVILEGES = 0x0020; 
    private const int TOKEN_ADJUST_GROUPS = 0x0040; 
    private const int TOKEN_ADJUST_DEFAULT = 0x0080; 
    private const int TOKEN_ADJUST_SESSIONID = 0x0100; 
    private const int STANDARD_RIGHTS_REQUIRED = 0x000F0000; 
    private const int TOKEN_ALL_ACCESS = 
     STANDARD_RIGHTS_REQUIRED | 
     TOKEN_ASSIGN_PRIMARY | 
     TOKEN_DUPLICATE | 
     TOKEN_IMPERSONATE | 
     TOKEN_QUERY | 
     TOKEN_QUERY_SOURCE | 
     TOKEN_ADJUST_PRIVILEGES | 
     TOKEN_ADJUST_GROUPS | 
     TOKEN_ADJUST_DEFAULT | 
     TOKEN_ADJUST_SESSIONID; 

    [StructLayout(LayoutKind.Sequential)] 
    private struct PROCESS_INFORMATION 
    { 
     public IntPtr hProcess; 
     public IntPtr hThread; 
     public int dwProcessId; 
     public int dwThreadId; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct SECURITY_ATTRIBUTES 
    { 
     public int nLength; 
     public IntPtr lpSecurityDescriptor; 
     public bool bInheritHandle; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct STARTUPINFO 
    { 
     public int cb; 
     public string lpReserved; 
     public string lpDesktop; 
     public string lpTitle; 
     public int dwX; 
     public int dwY; 
     public int dwXSize; 
     public int dwYSize; 
     public int dwXCountChars; 
     public int dwYCountChars; 
     public int dwFillAttribute; 
     public int dwFlags; 
     public short wShowWindow; 
     public short cbReserved2; 
     public IntPtr lpReserved2; 
     public IntPtr hStdInput; 
     public IntPtr hStdOutput; 
     public IntPtr hStdError; 
    } 

    private enum SECURITY_IMPERSONATION_LEVEL 
    { 
     SecurityAnonymous, 
     SecurityIdentification, 
     SecurityImpersonation, 
     SecurityDelegation 
    } 

    private enum TOKEN_TYPE 
    { 
     TokenPrimary = 1, 
     TokenImpersonation 
    } 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool CreateProcessAsUser(
     IntPtr hToken, 
     string lpApplicationName, 
     string lpCommandLine, 
     ref SECURITY_ATTRIBUTES lpProcessAttributes, 
     ref SECURITY_ATTRIBUTES lpThreadAttributes, 
     bool bInheritHandles, 
     int dwCreationFlags, 
     IntPtr lpEnvironment, 
     string lpCurrentDirectory, 
     ref STARTUPINFO lpStartupInfo, 
     out PROCESS_INFORMATION lpProcessInformation); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool DuplicateTokenEx(
     IntPtr hExistingToken, 
     int dwDesiredAccess, 
     ref SECURITY_ATTRIBUTES lpThreadAttributes, 
     int ImpersonationLevel, 
     int dwTokenType, 
     ref IntPtr phNewToken); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool OpenProcessToken(
     IntPtr ProcessHandle, 
     int DesiredAccess, 
     ref IntPtr TokenHandle); 

    [DllImport("userenv.dll", SetLastError = true)] 
    private static extern bool CreateEnvironmentBlock(
      ref IntPtr lpEnvironment, 
      IntPtr hToken, 
      bool bInherit); 

    [DllImport("userenv.dll", SetLastError = true)] 
    private static extern bool DestroyEnvironmentBlock(
      IntPtr lpEnvironment); 

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

    private static void LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock, int sessionId) 
    { 
     var pi = new PROCESS_INFORMATION(); 
     var saProcess = new SECURITY_ATTRIBUTES(); 
     var saThread = new SECURITY_ATTRIBUTES(); 
     saProcess.nLength = Marshal.SizeOf(saProcess); 
     saThread.nLength = Marshal.SizeOf(saThread); 

     var si = new STARTUPINFO(); 
     si.cb = Marshal.SizeOf(si); 
     si.lpDesktop = @"WinSta0\Default"; 
     si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK; 
     si.wShowWindow = SW_SHOW; 

     if (!CreateProcessAsUser(
      token, 
      null, 
      cmdLine, 
      ref saProcess, 
      ref saThread, 
      false, 
      CREATE_UNICODE_ENVIRONMENT, 
      envBlock, 
      null, 
      ref si, 
      out pi)) 
     { 
      throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateProcessAsUser failed"); 
     } 
    } 

    private static IDisposable Impersonate(IntPtr token) 
    { 
     var identity = new WindowsIdentity(token); 
     return identity.Impersonate(); 
    } 

    private static IntPtr GetPrimaryToken(Process process) 
    { 
     var token = IntPtr.Zero; 
     var primaryToken = IntPtr.Zero; 

     if (OpenProcessToken(process.Handle, TOKEN_DUPLICATE, ref token)) 
     { 
      var sa = new SECURITY_ATTRIBUTES(); 
      sa.nLength = Marshal.SizeOf(sa); 

      if (!DuplicateTokenEx(
       token, 
       TOKEN_ALL_ACCESS, 
       ref sa, 
       (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, 
       (int)TOKEN_TYPE.TokenPrimary, 
       ref primaryToken)) 
      { 
       throw new Win32Exception(Marshal.GetLastWin32Error(), "DuplicateTokenEx failed"); 
      } 

      CloseHandle(token); 
     } 
     else 
     { 
      throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed"); 
     } 

     return primaryToken; 
    } 

    private static IntPtr GetEnvironmentBlock(IntPtr token) 
    { 
     var envBlock = IntPtr.Zero; 
     if (!CreateEnvironmentBlock(ref envBlock, token, false)) 
     { 
      throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateEnvironmentBlock failed"); 
     } 
     return envBlock; 
    } 

    public static void LaunchAsCurrentUser(string cmdLine) 
    { 
     var process = Process.GetProcessesByName("explorer").FirstOrDefault(); 
     if (process != null) 
     { 
      var token = GetPrimaryToken(process); 
      if (token != IntPtr.Zero) 
      { 
       var envBlock = GetEnvironmentBlock(token); 
       if (envBlock != IntPtr.Zero) 
       { 
        LaunchProcessAsUser(cmdLine, token, envBlock, process.SessionId); 
        if (!DestroyEnvironmentBlock(envBlock)) 
        { 
         throw new Win32Exception(Marshal.GetLastWin32Error(), "DestroyEnvironmentBlock failed"); 
        } 
       } 

       CloseHandle(token); 
      } 
     } 
    } 

    public static IDisposable ImpersonateCurrentUser() 
    { 
     var process = Process.GetProcessesByName("explorer").FirstOrDefault(); 
     if (process != null) 
     { 
      var token = GetPrimaryToken(process); 
      if (token != IntPtr.Zero) 
      { 
       return Impersonate(token); 
      } 
     } 

     throw new Exception("Could not find explorer.exe"); 
    } 
} 

Bạn có thể sử dụng nó như thế:

ImpersonationUtils.LaunchAsCurrentUser("notepad"); 

using (ImpersonationUtils.ImpersonateCurrentUser()) 
{ 

} 

More giải thích và ví dụ bạn có thể tìm thấy ở đây:

Impersonating CurrentUser from SYSTEM

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