Олицетворение пользователя Windows
Я использую код для олицетворения учетной записи пользователя, чтобы получить доступ к файловому ресурсу.
public class Impersonator :
IDisposable
{
#region Public methods.
// ------------------------------------------------------------------
/// <summary>
/// Constructor. Starts the impersonation with the given credentials.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
public Impersonator(
string userName,
string domainName,
string password )
{
ImpersonateValidUser( userName, domainName, password );
}
// ------------------------------------------------------------------
#endregion
#region IDisposable member.
// ------------------------------------------------------------------
public void Dispose()
{
UndoImpersonation();
}
// ------------------------------------------------------------------
#endregion
#region P/Invoke.
// ------------------------------------------------------------------
[DllImport("advapi32.dll", SetLastError=true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
// ------------------------------------------------------------------
#endregion
#region Private member.
// ------------------------------------------------------------------
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private void ImpersonateValidUser(
string userName,
string domain,
string password )
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
try
{
if ( RevertToSelf() )
{
if ( LogonUser(
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();
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
finally
{
if ( token!= IntPtr.Zero )
{
CloseHandle( token );
}
if ( tokenDuplicate!=IntPtr.Zero )
{
CloseHandle( tokenDuplicate );
}
}
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if ( impersonationContext!=null )
{
impersonationContext.Undo();
}
}
private WindowsImpersonationContext impersonationContext = null;
// ------------------------------------------------------------------
#endregion
}
затем с помощью:
using (new Impersonator("username", "domain", "password"))
{
Process.Start("explorer.exe", @"/root,server01-Prodabc");
}
Я получаю ошибку "Доступ запрещен".
этот пользователь предположительно имеет доступ к этому ресурсу. Я могу сопоставить диск, использовать "net use", но этот код не будет работать. Теперь я думаю, что это код. Кто-нибудь что-нибудь видит? Есть ли лучший способ сделать это?
3 ответов
попробуйте это :
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken);
использование :
IntPtr userToken = IntPtr.Zero;
bool success = External.LogonUser(
"john.doe",
"domain.com",
"MyPassword",
(int) AdvApi32Utility.LogonType.LOGON32_LOGON_INTERACTIVE, //2
(int) AdvApi32Utility.LogonProvider.LOGON32_PROVIDER_DEFAULT, //0
out userToken);
if (!success)
{
throw new SecurityException("Logon user failed");
}
using (WindowsIdentity.Impersonate(userToken))
{
Process.Start("explorer.exe", @"/root,\server01-Prod\abc");
}
Если я правильно понимаю, ваше намерение состоит в том, чтобы запустить процесс в контексте олицетворения.
документ из CreateProcess (который используется процессом.Начала) говорит: Если вызывающий процесс от имени другого пользователя, новый процесс использует маркер для вызывающего процесса, а не маркер олицетворения. Чтобы запустить новый процесс в контексте безопасности пользователя, представленного маркером олицетворения, используйте CreateProcessAsUser или CreateProcessWithLogonW функция.
Итак, вы используете неправильный API для этого.
вместо Impersonator
класс, что происходит, когда вы называете Process.Start
и передать ProcessStartInfo
экземпляр, который содержит имя пользователя, пароль и домен, который вы хотите запустить процесс?
возможно, если это работает, то ваш Impersonator
класс должен создать ProcessStartInfo
экземпляр и использовать это для создания новых процессов (инкапсулировать, что внутри самого класса).
var psi = new ProcessStartInfo("explorer.exe", @"/root,\server01-Prod\abc");
psi.Domain = domain;
psi.UserName = username;
psi.Password = password;
psi.WorkingDirectory = workingDir;
Process.Start(psi);
кроме того,документы MSDN...
настройка свойств домена, имени пользователя и пароля в Объект ProcessStartInfo рекомендуется для запуска процесс с учетными данными пользователя.
вы также должны установить рабочий каталог при запуске процесса с различными пользовательскими кредитами.