【问题标题】:How to set ASP.NET security impersonation如何设置 ASP.NET 安全模拟
【发布时间】:2011-12-28 17:30:42
【问题描述】:

我正在经历

http://www.codeassociate.com/caapi/html/T_CA_Common_Security_Impersonate.htm

我不想硬编码域\用户名和密码。

是否可以获取当前的 Windows 用户凭据并通过它?

【问题讨论】:

    标签: c# asp.net impersonation


    【解决方案1】:

    不,您无法在客户端检测到用户并冒充他们的帐户。

    一种可能的解决方法...

    我不知道这是否可行,我并不是说这是一个好主意,但如果您可以提示用户输入他们的凭据,您也许可以使用编程模拟。这是一个你可以使用的类:

    /// <summary>
    /// Leverages the Windows API (advapi32.dll) to programmatically impersonate a user.
    /// </summary>
    public class ImpersonationContext : IDisposable
    {
        #region constants
    
        private const int LOGON32_LOGON_INTERACTIVE = 2;
        private const int LOGON32_PROVIDER_DEFAULT = 0;
    
        #endregion
    
        #region global variables
    
        private WindowsImpersonationContext impersonationContext;
        private bool impersonating;
    
        #endregion
    
        #region unmanaged code
    
        [DllImport("advapi32.dll")]
        private static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
    
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool RevertToSelf();
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern bool CloseHandle(IntPtr handle);
    
        #endregion
    
        #region constructors
    
        public ImpersonationContext()
        {
            impersonating = false;
        }
    
        /// <summary>
        /// Overloaded constructor and begins impersonating.
        /// </summary>
        public ImpersonationContext(string userName, string password, string domain)
        {
            this.BeginImpersonationContext(userName, password, domain);
        }
    
        #endregion
    
        #region impersonation methods
    
        /// <summary>
        /// Begins the impersonation context for the specified user.
        /// </summary>
        /// <remarks>Don't call this method if you used the overloaded constructor.</remarks>
        public void BeginImpersonationContext(string userName, string password, string domain)
        {
            //initialize token and duplicate variables
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;
    
            if (RevertToSelf())
            {
                if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        using (WindowsIdentity tempWindowsIdentity = new WindowsIdentity(tokenDuplicate))
                        {
                            //begin the impersonation context and mark impersonating true
                            impersonationContext = tempWindowsIdentity.Impersonate();
                            impersonating = true;
                        }
                    }
                }
            }
    
            //close the handle to the account token
            if (token != IntPtr.Zero)
                CloseHandle(token);
    
            //close the handle to the duplicated account token
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
        }
    
        /// <summary>
        /// Ends the current impersonation context.
        /// </summary>
        public void EndImpersonationContext()
        {
            //if the context exists undo it and dispose of the object
            if (impersonationContext != null)
            {
                //end the impersonation context and dispose of the object
                impersonationContext.Undo();
                impersonationContext.Dispose();
            }
    
            //mark the impersonation flag false
            impersonating = false;
        }
    
        #endregion
    
        #region properties
    
        /// <summary>
        /// Gets a value indicating whether the impersonation is currently active.
        /// </summary>
        public bool Impersonating
        {
            get
            {
                return impersonating;
            }
        }
    
        #endregion
    
        #region IDisposable implementation
    
        ~ImpersonationContext()
        {
            Dispose(false);
        }
    
        public void Dispose()
        {
            Dispose(true);               
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (impersonationContext != null)
                {
                    impersonationContext.Undo();
                    impersonationContext.Dispose();
                }
            }
        }
    
        #endregion    
    }
    

    这是你如何实现这个类的:

    using (ImpersonationContext context = new ImpersonationContext("user", "password", "domain")) 
    { 
        if (context.Impersonating) 
        { 
            //impersonating
        } 
    }
    

    【讨论】:

    • 如果用户已经登录..这个解决方案不起作用。如果您想模拟另一个帐户(即服务帐户),它确实有效......我更喜欢。
    • @UweKeim:这与我上面的类似。
    • @EdB:不确定你的意思。你能再解释一下吗?
    【解决方案2】:

    假设您在站点上使用 Windows 集成身份验证,您可以使用 User.Identity 获取用户的凭据。

    添加参考:

    using System.Security.Principal;
    

    使用它来模拟网络上的当前用户。

    WindowsIdentity wi = (WindowsIdentity)User.Identity;
    WindowsImpersonationContext wic = null;
    
    try
    {
        wic = wi.Impersonate();
    
        if (wi.IsAuthenticated)
        {
             //Do stuff here on network as Current User
             // i.e. asyncFileUpload.SaveAs(location);
        }
    
    }
    catch(Exception ex)
    {
        //Log Error Here
    
        if (wic != null)
          wic.Undo();
    
        return;
    }
    finally
    {
         if (wic != null)
             wic.Undo();
    }
    

    确保登录用户对他们将要访问的网络资源具有权限

    【讨论】:

    • 请注意:您不需要在 catch 中调用 wic.Undo()。无论 try 块成功完成还是 catch 块结束,finally 块都会运行。
    猜你喜欢
    • 2010-12-26
    • 1970-01-01
    • 2017-01-27
    • 2016-07-28
    • 2012-04-01
    • 2010-11-29
    • 2014-04-05
    • 2015-06-14
    • 1970-01-01
    相关资源
    最近更新 更多