在ASP.NET中模拟时访问映射的驱动器

时间:2010-04-19 17:58:00

标签: asp.net networking impersonation mapped-drive

短版是否可以在ASP.NET中使用模拟来访问映射的驱动器?

长版:

我目前正在ASP.NET中使用模拟来获取对网络文件的访问权限。这对于使用UNC路径的任何网络文件都是完美的,但它无法访问为我假冒的用户帐户定义的映射驱动器上的任何文件。

例如,假设某个文件位于\\machine\folder\file.txt网络上,我们还说驱动器S:已映射到\\machine\folder。我们需要能够访问完整的UNC路径\\machine\folder\file.txt以及较短的映射驱动路径S:\file.txt

显然,标准的ASP.NET进程也无法访问。

使用在本地帐户下运行的映射S:驱动器的控制台应用程序,调用File.Exists(@"\\machine\folder\file.txt")返回true,File.Exists(@"S:\file.txt")也返回true。

但是,在使用相同本地帐户的ASP.NET上下文中进行模拟时,只有File.Exists(@"\\machine\folder\file.txt")返回true。 File.Exists(@"S:\file.txt")返回false。

我正在使用在我的本地Windows 7 Professional机器上运行的IIS 7进行测试,但这需要在IIS 6和IIS 7中运行。

模拟由C#中的几个类处理,我将在此处包含:

public static class Impersonation
{
    private static WindowsImpersonationContext context;

    public static void ImpersonateUser(string username, string password)
    {
        ImpersonateUser(".", username, password);
    }

    public static void ImpersonateUser(string domain, string username, string password)
    {
        StopImpersonating();

        IntPtr userToken;
        var returnValue = ImpersonationImports.LogonUser(username, domain, password,
                                                  ImpersonationImports.LOGON32_LOGON_INTERACTIVE,
                                                  ImpersonationImports.LOGON32_PROVIDER_DEFAULT,
                                                  out userToken);
        context = WindowsIdentity.Impersonate(userToken);
    }

    public static void StopImpersonating()
    {
        if (context != null)
        {
            context.Undo();
            context = null;
        }
    }
}

public static class ImpersonationImports
{
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_LOGON_NETWORK = 3;
    public const int LOGON32_LOGON_BATCH = 4;
    public const int LOGON32_LOGON_SERVICE = 5;
    public const int LOGON32_LOGON_UNLOCK = 7;
    public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
    public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken
        );
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int ImpersonateLoggedOnUser(
        IntPtr hToken
    );

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int RevertToSelf();

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int CloseHandle(IntPtr hObject);
}

然后,在Page_Load期间,我们基本上做了这样的事情:

Impersonation.ImpersonateUser("DOMAIN", "username", "password");

if (!File.Exists(@"S:\file.txt"))
     throw new WeCannotContinueException();

我意识到使用映射驱动器不是最佳做法,但由于遗留原因,它对我们的业务来说是可取的。 是否可以在ASP.NET中使用模拟来访问映射的驱动器?

3 个答案:

答案 0 :(得分:1)

不,但您可以使用符号链接。 Mklink /d将创建目录链接。

答案 1 :(得分:0)

您只能访问由模拟用户创建的映射驱动器。

因此,如果您冒充用户X然后映射共享(例如,通过网络使用),那么只要模拟生效,该共享就会可见。

您可以通过DriveInfo.GetDrives()确定当前可以访问的映射驱动器。具有DriveType of Network的驱动器可在当前安全上下文中访问。

答案 2 :(得分:0)

我尝试了mklink solution from Scott,但它无法使用ASP.NET。

至于arnshea的回答:它根本不起作用;我甚至模仿域管理员,并将所有权限设置为所有人,iuser和网络服务。

所以唯一的解决方案是:在设计Web应用程序时,您必须决定是否要保存到网络资源并使用UNC协议。

映射的网络驱动器不能与ASP.NET一起用于常规文件操作。