模拟整个应用程序生命周期

时间:2014-03-20 20:56:55

标签: c# impersonation

我一直在使用此link来设置模拟。我有很多方法,我需要冒充他们所有人。

  1. 我是否必须在每个方法调用周围添加使用代码或是否存在 一种为整个生命周期设置模仿的方法 申请?
  2. 我冒充下面的本地管理员 - 是 我的代码有任何缺陷或安全隐患吗?
  3. 是下面2的正确LOGON32_LOGON_NEW_CREDENTIALS值(它按预期工作)
  4. c#代码

    private void buttonUsingImpersonation_Click(object sender, EventArgs e)
            {
                try
                {               
                    using (new Impersonation("LocalHost", "test", "test"))
                    {
                        // do whatever you want
    
                        string fileName = System.IO.Path.GetRandomFileName();
                        String pathString = System.IO.Path.Combine(FolderPath, fileName);
    . 
                        if (!System.IO.File.Exists(pathString))
                        {
                            using (System.IO.FileStream fs = System.IO.File.Create(pathString))
                            {
                                for (byte i = 0; i < 100; i++)
                                {
                                    fs.WriteByte(i);
                                }
                            }
                        }
                        else
                        {
                            MessageBox.Show("File already exists " + fileName);
    
                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    // If exception happens, it will be returned here
                    MessageBox.Show("Error " + MethodBase.GetCurrentMethod().Name + " " + ex.ToString());
                }
            }
    

    using System;
    using System.Runtime.ConstrainedExecution;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Security.Permissions;
    using System.Security.Principal;
    using Microsoft.Win32.SafeHandles;
    
    namespace ImpersonationDemo
    {
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public class Impersonation : IDisposable
        {
            private readonly SafeTokenHandle _handle;
            private readonly WindowsImpersonationContext _context;
    
            const int LOGON32_LOGON_NEW_CREDENTIALS = 2;
    
            public Impersonation(string domain, string username, string password)
            {
                var ok = LogonUser(username, domain, password,
                               LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle);
                if (!ok)
                {
                    var errorCode = Marshal.GetLastWin32Error();
                    throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code {0}.", errorCode));
                }
    
                this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
            }
    
            public void Dispose()
            {
                this._context.Dispose();
                this._handle.Dispose();
            }
    
            [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
    
            public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
            {
                private SafeTokenHandle()
                    : base(true) { }
    
                [DllImport("kernel32.dll")]
                [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
                [SuppressUnmanagedCodeSecurity]
                [return: MarshalAs(UnmanagedType.Bool)]
                private static extern bool CloseHandle(IntPtr handle);
    
                protected override bool ReleaseHandle()
                {
                    return CloseHandle(handle);
                }
            }
        }
    }
    

1 个答案:

答案 0 :(得分:1)

有很多方法可以做到这一点,而不是一个正确的方法。一种方法是将您想要模拟的方法作为委托传递给某种ImpersonatedContext类,它将在您的模拟范围中包装调用。这也将使所有逻辑远离按钮单击事件处理程序,这在结构上也不是最佳方式。

关于您的安全问题,截至目前您正在直接指定用户名和密码。如果Eve要反编译你的代码,她就能看到密码。也许你应该让用户指定管理员密码?

我一直在使用示例代码,它对我来说很好。我认为LOGON32_LOGON_NEW_CREDENTIALS没问题。您可以阅读有关不同模式here (LogonUser)

的更多信息

<强>更新 我想快速看看它会是什么样子,就像这样。您传递的委托接受一个对象,并返回一个成功值作为布尔值。您可以根据自己的需要进行修改。

public class ImpersonationContext {
    public delegate bool ImpersonationDel(object obj);

    public bool Invoke(ImpersonationDel del){
        using (new Impersonation("LocalHost", "test", "test")){
            return del.Invoke();
        }
    }
}