Accessing mapped drives when impersonating in ASP.

2019-03-22 09:27发布

问题:

Short version: Is it possible or not to use impersonation in ASP.NET to access mapped drives?

Long Version:

I'm currently using impersonation in ASP.NET to gain access to network files. This is working perfectly for any network file using a UNC path, but it is failing to access any files on mapped drives defined for the user account I'm impersonating.

For example, let's say a file lives on the network at \\machine\folder\file.txt, and let's also say that drive S: is mapped to \\machine\folder. We need to be able to access both the full UNC path, \\machine\folder\file.txt, as well as the shorter, mapped drive path, S:\file.txt.

Obviously the standard ASP.NET process cannot access either.

Using a console application that runs under the local account with the mapped S: drive, calling File.Exists(@"\\machine\folder\file.txt") returns true, and File.Exists(@"S:\file.txt") also returns true.

However, when impersonating in an ASP.NET context with the same local account, only File.Exists(@"\\machine\folder\file.txt") returns true. File.Exists(@"S:\file.txt") returns false.

I'm testing with IIS 7 running on my local Windows 7 Professional box, though this will need to run in both IIS 6 and IIS 7.

Impersonation is handled with a couple of classes in C# which I'll include here:

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);
}

Then, during Page_Load, we basically do something like this:

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

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

I realize using mapped drives isn't a best practice, but for legacy reasons it's desirable for our business. Is it possible or not to use impersonation in ASP.NET to access mapped drives?

回答1:

No, but you can use a symbolic link instead. Mklink /d will create a directory link.



回答2:

You can only access mapped drives that were created by the user being impersonated.

So if you were to impersonate user X then map the share (e.g., via net use) then that share will be visible for as long as the impersonation is in effect.

You can determine which mapped drives are currently accessible via DriveInfo.GetDrives(). Drives with a DriveType of Network are accessible in the current security context.



回答3:

I tried the mklink solution from Scott, and it is not working with ASP.NET.

As for answer from arnshea: it is not working at all; I even impersonated with the domain administrator, and all permissions set to everyone, iuser and network service.

So the only solution: when you design your web application you must decide whether you want to save to network resource and use the UNC protocol for that.

A mapped network drive does not work with ASP.NET for regular file operations.