Пример #1
0
        /// <summary>
        /// Impersonates the specified user account.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="domainName">Name of the domain.</param>
        /// <param name="password">The password. <see cref="String"/></param>
        /// <param name="logonType">Type of the logon.</param>
        /// <param name="logonProvider">The logon provider.</param>
        /// /// <param name="impersonationAction">A callback to perform during the impersonation initialization.</param>
        public virtual void Impersonate(string userName, string domainName, SecureString password, LogonType logonType, LogonProvider logonProvider, Action <IntPtr> impersonationAction = null)
        {
            UndoImpersonation();

            IntPtr logonToken          = IntPtr.Zero;
            IntPtr logonTokenDuplicate = IntPtr.Zero;
            IntPtr passwordPtr         = new IntPtr();

            passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password);
            bool logonValue = false;

            try
            {
                // revert to the application pool identity, saving the identity of the current requestor
                this._wic = WindowsIdentity.Impersonate(IntPtr.Zero);

                // do logon & impersonate
                logonValue = Win32NativeMethods.LogonUser(
                    userName,
                    domainName,
                    passwordPtr,
                    (int)logonType,
                    (int)logonProvider,
                    ref logonToken);

                if (logonValue)
                {
                    Win32NativeMethods.SECURITY_ATTRIBUTES sa = new Win32NativeMethods.SECURITY_ATTRIBUTES();
                    sa.nLength = (uint)Marshal.SizeOf(sa);

                    if (Win32NativeMethods.DuplicateTokenEx(
                            logonToken,
                            Win32NativeMethods.TOKEN_ASSIGN_PRIMARY | Win32NativeMethods.TOKEN_DUPLICATE | Win32NativeMethods.TOKEN_QUERY,
                            ref sa,
                            (int)Win32NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                            (int)Win32NativeMethods.TOKEN_TYPE.TokenPrimary,
                            ref logonTokenDuplicate))
                    {
                        // Looks like it is working without impersonating. To be revisited.
                        ////var wi = new WindowsIdentity(logonTokenDuplicate);
                        ////wi.Impersonate(); // discard the returned identity context (which is the context of the application)
                        ////this.IsImpersonating = true;
                        if (impersonationAction != null)
                        {
                            impersonationAction(logonTokenDuplicate);
                        }
                    }
                    else
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }
                }
                else
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr);

                if (logonToken != IntPtr.Zero)
                {
                    Win32NativeMethods.CloseHandle(logonToken);
                }

                if (logonTokenDuplicate != IntPtr.Zero)
                {
                    Win32NativeMethods.CloseHandle(logonTokenDuplicate);
                }
            }
        }