我需要通过Directory.GetDirectories()和Directory.GetFiles()方法访问当前IPrincipal可以访问的文件和目录,而无需列出其他文件。进程本身作为NETWORK SERVICE运行,因此它必须在这些调用期间将主体更改为当前用户(通过IPrincipal)。
我试图在文件访问部分之前将Thread.CurrentPrincipal更改为新的IPrincipal,但它似乎没有什么区别。
我还能做些什么,或者我错过了什么?
答案 0 :(得分:5)
Windows模拟通过使用登录详细信息获取用户令牌来解决此问题。然后可以使用此令牌获取WindowsIdentity,然后将其用于生成模拟上下文。在此上下文范围内,您可以将文件系统作为模拟用户访问。
当然,您需要存储用于此方法的用户名和密码。
首先,定义从Windows获取用户令牌所需的Windows API:
internal class WindowsAPI
{
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_LOGON_INTERACTIVE = 2;
[DllImport( "advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
public static extern bool LogonUser( String lpszUsername,
String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken
);
[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
public extern static bool CloseHandle( IntPtr handle );
}
然后,使用这些API获取WindowsIdentity:
private WindowsIdentity GetIdentity( string userName, string password )
{
_userToken = IntPtr.Zero;
if ( !WindowsAPI.LogonUser(
userName,
AbbGrainDomain,
password,
WindowsAPI.LOGON32_LOGON_INTERACTIVE, WindowsAPI.LOGON32_PROVIDER_DEFAULT,
ref _userToken
) )
{
int errorCode = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception( errorCode );
}
return new WindowsIdentity( _userToken );
}
最后,使用此标识生成模拟上下文:
public List<string> GetDirectories( string searchPath )
{
using ( WindowsImpersonationContext wic = GetIdentity().Impersonate() )
{
var directories = new List<string>();
var di = new DirectoryInfo( searchPath );
directories.AddRange( di.GetDirectories().Select( d => d.FullName ) );
return directories;
}
}
最后,使用存储的_userToken,使用IDisposable模式清理Windows句柄非常重要:
if ( _userToken != IntPtr.Zero )
WindowsAPI.CloseHandle( _userToken );
答案 1 :(得分:0)
我不认为你这样做是正确的。你应该考虑使用模仿。例如,请查看this教程,了解如何执行此操作。
答案 2 :(得分:-1)
您可以使用DllImport和LogonUser win32 API来模拟其他用户。