Является ли вход в систему с олицетворением .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) члены этого типа потокобезопасны. Потокобезопасность любых членов экземпляра не гарантируется.

Класс подражателя :

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
}
13
задан Peter Mortensen 13 December 2017 в 00:12
поделиться