0

ファイル共有上のファイルにアクセスするときに、ユーザーがログオンしたユーザー ID 以外のユーザー ID を偽装する必要がある C# Windows アプリケーションがあります。偽装を使用してこのユーザーに切り替えてから元に戻します。また、ローカル ファイルにアクセスするには、ログオンしているユーザーに戻す必要があります。アプリケーションによってキャッチされていない System.ExecutionEngineException が発生し、停止します。これがコードです。このエラーが発生する理由や、より良い方法についての提案。

編集: アプリケーションは、DevExpress による XAF フレームワークを使用しています。

public static class Impersonation
{
    #region Fields
    public static WindowsImpersonationContext newUser;
    public static string domain;
    public static string userName;
    public static string password;
    #endregion
    // group type enum
    private enum SECURITY_IMPERSONATION_LEVEL : int
    {
        SecurityAnonymous = 0,
        SecurityIdentification = 1,
        SecurityImpersonation = 2,
        SecurityDelegation = 3
    }
    // obtains user token
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

    // closes open handes returned by LogonUser
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private extern static bool CloseHandle(IntPtr handle);

    // creates duplicate token handle
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

    #region Methods
    public static void RevertUser()
    {
        newUser.Undo();
    }
    #region ImpersonateApexApplicationUser
    /// <summary>
    /// Attempts to impersonate a user.  If successful, returns 
    /// a WindowsImpersonationContext of the new users identity.
    /// </summary>
    /// <param name="sUsername">Username you want to impersonate</param>
    /// <param name="sDomain">Logon domain</param>
    /// <param name="sPassword">User's password to logon with</param></param>
    /// <returns></returns>
    public static void ImpersonateApexApplicationUser()
    {
        // initialize tokens
        IntPtr pExistingTokenHandle = new IntPtr(0);
        IntPtr pDuplicateTokenHandle = new IntPtr(0);
        pExistingTokenHandle = IntPtr.Zero;
        pDuplicateTokenHandle = IntPtr.Zero;

        try
        {
            const int LOGON32_PROVIDER_DEFAULT = 0;
            const int LOGON32_LOGON_INTERACTIVE = 2;

            if (!LogonUser(userName, domain, Encryption.Decrypt(password), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle))
                throw new Exception(string.Format("LogonUser() failed with error code {0}", Marshal.GetLastWin32Error()));
            else
                if (!DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle))
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    CloseHandle(pExistingTokenHandle); // close existing handle
                    throw new Exception(string.Format("DuplicateToken() failed with error code: {0}", errorCode));
                }
                else
                {
                    // create new identity using new primary token
                    WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle);
                    newUser = newId.Impersonate();
                }
        }

        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            // close handle(s)
            if (pExistingTokenHandle != IntPtr.Zero)
                CloseHandle(pExistingTokenHandle);
            if (pDuplicateTokenHandle != IntPtr.Zero)
                CloseHandle(pDuplicateTokenHandle);
        }
    }
    #endregion

}

プログラムの最初に、次のように呼び出します。

    Impersonation.domain = "xxxx";
    Impersonation.userName = "xxxx;
    Impersonation.password = "xxxx";
    Impersonation.ImpersonateApexApplicationUser();

その後:

Impersonation.ImpersonateApexApplicationUser(); 
//file share access code
Impersonation.RevertUser();
4

0 に答える 0