【问题标题】:Impersonation with Win32 API to access network share versus reading network share with Windows Explorer?使用 Win32 API 模拟访问网络共享与使用 Windows 资源管理器读取网络共享?
【发布时间】:2011-12-09 12:24:59
【问题描述】:

我有一个使用 Win32 API 模拟的 Web 应用程序。我最近出差回来,发现应用程序中冒充失败的部分。

模拟的原因是存在用于特定目的的网络共享。当我的 Web 应用程序访问该网络共享时,它必须模拟一个特殊帐户。为了便于讨论,uid 为“Bob”,密码为“1234”,域为“home”。

两周前,我编写了使用 Win32 API 模拟 Bob 的程序,一切顺利。现在,Win32 API 指示登录失败。我很难弄清楚可能会发生什么变化。 具体来说,服务器表明它无法冒充 Bob。该错误发生在服务器实际尝试访问网络共享之前。

奇怪的是,如果我使用 MSTSC 连接到我的 Web 服务器,我可以在 Windows 资源管理器中单击“映射网络驱动器”并使用 Bob@home 和密码 1234 访问文件。(我输入通过单击“映射网络驱动器”对话框中的“使用不同的用户名连接”来获取 uid 和密码)

当我尝试使用模拟访问我的网络共享与使用 Windows 资源管理器访问我的网络共享时,似乎一定会发生一些不同的事情。

有什么区别?

更新:我觉得这个问题的答案是,当我通过 Windows 资源管理器访问我的文件时,某种登录权限被拒绝了。

【问题讨论】:

  • 您是否在询问通过模拟访问共享与通过 Windows 资源管理器从您计算机上的帐户访问共享之间的区别?可以发一些代码吗?
  • 我在问通过模拟访问共享与使用用于模拟的相同帐户通过 Windows 资源管理器访问共享有什么区别
  • 您是否验证了共享的权限?我假设您为文件夹指定了权限,但很多人忘记将权限应用于共享。
  • 是的,权限已经过验证。我可以从网络上的任何地方访问该文件夹;我只是无法通过模拟访问它。
  • 您是否在调用代码中指定域?

标签: asp.net login impersonation file-sharing network-share


【解决方案1】:

确保您使用 UNC 路径访问文件夹:

string path = @"\\server\folder";

我不知道您的模拟类是什么样的,但这是我用于类似任务的类:

/// <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     
} 

使用ImpersonationContext

using (ImpersonationContext context = new ImpersonationContext("user", "password", "domain")) 
{ 
    if (context.Impersonating) 
    { 
        Process.Start(@"/Support/SendFax/SendFax.exe"); 
    } 
} 

【讨论】:

  • 我的代码和你的很相似。问题是我的代码曾经可以工作,但现在不行了。
  • @RiceFlourCookies:这似乎表明某处的权限发生了变化。您是否尝试过临时授予对该文件夹的无限制访问权限,即授予所有人完全权限?
  • 当我通过调试器运行我的代码时,它在尝试开始模拟时失败。具体来说,服务器甚至尝试访问网络共享之前引发异常。
  • 嗯...您确定用户帐户处于活动状态?你的代码在冒充用户之前是否调用了RevertToSelf()
  • 是的,它调用 RevertToSelf()。我还发现,当代码在我的本地工作站上的 Casini 中运行时,它似乎可以工作。但是,它在我的开发和生产 Web 服务器上都失败了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
  • 2012-06-27
相关资源
最近更新 更多