Dot-Net
.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 對象,作為我命名為“Impersonator”的類型實例中的私有狀態欄位(程式碼如下)。因此,由於此 WindowsImpersonationContext 對像是此類型實例中的本地私有欄位,並且每次我想模擬某些憑據集時都會創建此類型的新實例,因此我可以假設此 WindowsImpersonationContext 是用於在塊內執行程式碼期間執行所有 ACL 驗證,例如
using (Impersonator.Impersonate(userId, domain, password)) { // Code I want to execute using supplied credentials }我擔心的是 MSDN 頁面WindowsImpersonationContext上的聲明:
此類型的任何公共靜態(在 Visual Basic 中為 Shared)成員都是執行緒安全的。不保證任何實例成員都是執行緒安全的。
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 }
它與任何事物無關。您擁有的句柄是登錄句柄。一旦你有了它,你就可以使用該句柄線上程上(通過呼叫
WindowsIdentity.Impersonate)或程序(通過CreateProcessAPI 函式或通過線上程上模擬,然後在模擬使用者時創建新Process實例)來模擬使用者。無論哪種方式,呼叫
LogonUserAPI 函式都不會執行任何模擬,它只是為您提供執行模擬所需的使用者句柄(假設您有權限)。