【发布时间】:2011-05-11 07:51:53
【问题描述】:
我一直在用 C# (.net4) 开发一个项目。 Project 几乎允许人们将文件从本地计算机上传到网络共享。
网络共享是安全的。它只能由在活动目录中创建的名为“代理”的用户访问。
我做了一些研究,发现了我用来模拟的这个类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace Datacom.CorporateSys.Utilities
{
public class ImpersonateUser
{
[DllImport("advapi32.dll")]
public 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)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
WindowsImpersonationContext impersonationContext;
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
private string p;
private string p_2;
private string p_3;
private String UserName
{
set;
get;
}
private String Domain
{
set;
get;
}
private String Password
{
set;
get;
}
/// <summary>
/// Impersonates the user.
/// </summary>
/// <param name="userName">Name of the user.</param>
/// <param name="domain">The domain.</param>
/// <param name="password">The password.</param>
public ImpersonateUser(string userName, string domain, string password)
{
UserName = userName;
Domain = domain;
Password = password;
}
/// <summary>
/// Impersonates the valid user.
/// </summary>
/// <returns></returns>
public bool impersonateValidUser()
{
WindowsIdentity tempWindowsIdentity;
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)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
/// <summary>
/// Undoes the impersonation.
/// </summary>
public void undoImpersonation()
{
impersonationContext.Undo();
}
}
}
注意:根据记忆,我想我在 msdn 上找到了这个作为示例。
这就是我尝试将文件从本地路径移动到网络的方式
if (imp.impersonateValidUser())
{
System.IO.File.Copy(local_file, server_file, true);
imp.undoImpersonation();
}
else
{
throw new Exception("Unable to impersonate for uploading file.");
}
而且它有效!我从来没有遇到过模拟问题 - 永远不会抛出异常。它工作正常并将文件上传到服务器。但是,当我开始进行更多测试时,我发现如果代理用户没有登录到服务器(通常我打开 RDS 登录并退出 - 没有注销)。
我得到不同的异常 - 找不到网络路径异常,它仅在我刚刚重新启动服务器并且“代理”未登录时发生。
我的第一个想法是模拟类有问题,但是它在工作时模拟得很好(即文件具有代理用户的所有权)。然后我认为可能需要登录“代理”,以便操作系统可以使用其权限来实际访问 \server\uploads
我现在非常迷茫,不知道如何解决它。 请注意:我无法控制服务器。服务器是安装了桌面体验的win2k8(否则我无法访问任何网络位置)。
谢谢!
【问题讨论】:
-
我做了一些调查。给我的网络路径实际上是通过 WebDAV 访问的,因此我被建议在我们的 WinServer 2k8 上安装桌面体验。此示例适用于普通的“网络”共享。但是,它无法通过 WebDAV 重定向器(桌面体验)模拟到 webDAV。 learn.iis.net/page.aspx/386/using-the-webdav-redirector
标签: networking c#-4.0 impersonation