简短版本:是否可以在 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")
返回假。
我正在测试在我的本地 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 中使用模拟来访问映射驱动器?