LogonUser y la delegación
-
13-09-2019 - |
Pregunta
Estoy usando la API LogonUser Win32:
token = LogonUser(...)
WindowsIdentity newId = new WindowsIdentity(token);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
Sin embargo cuando se llama a un servicio WCF después de esto yo no soy capaz de utilizar la identidad suplantada. Creo que esto se debe a que es igual impersonatedUser.ImpersonationLevel suplantación.
Es esta la razón? Es un nivel de ImpersonationLevel.Identification lo que necesito? Como llegar a tal nivel?
Solución
No sé si esto funcionará para WCF. Pero lo usamos en nuestra aplicación Web de producción para la suplantación de leer y escribir archivos en el sistema de archivos. Tendrá que definir las API para AdvApi32.LogonUser, AdvApi32.DuplicateToken y Kernel32.CloseHandle y asegúrese de cerrar la WindowsImpersonationContext cuando haya terminado.
/// <summary>impersonates a user</summary>
/// <param name="username">domain\name of the user account</param>
/// <param name="password">the user's password</param>
/// <returns>the new WindowsImpersonationContext</returns>
public static WindowsImpersonationContext ImpersonateUser(String username, String password)
{
WindowsIdentity winId = WindowsIdentity.GetCurrent();
if (winId != null)
{
if (string.Compare(winId.Name, username, true) == 0)
{
return null;
}
}
//define the handles
IntPtr existingTokenHandle = IntPtr.Zero;
IntPtr duplicateTokenHandle = IntPtr.Zero;
String domain;
if (username.IndexOf("\\") > 0)
{
//split domain and name
String[] splitUserName = username.Split('\\');
domain = splitUserName[0];
username = splitUserName[1];
}
else
{
domain = String.Empty;
}
try
{
//get a security token
bool isOkay = AdvApi32.LogonUser(username, domain, password,
(int) AdvApi32.LogonTypes.LOGON32_LOGON_INTERACTIVE,
(int) AdvApi32.LogonTypes.LOGON32_PROVIDER_DEFAULT,
ref existingTokenHandle);
if (!isOkay)
{
int lastWin32Error = Marshal.GetLastWin32Error();
int lastError = Kernel32.GetLastError();
throw new Exception("LogonUser Failed: " + lastWin32Error + " - " + lastError);
}
// copy the token
isOkay = AdvApi32.DuplicateToken(existingTokenHandle,
(int) AdvApi32.SecurityImpersonationLevel.SecurityImpersonation,
ref duplicateTokenHandle);
if (!isOkay)
{
int lastWin32Error = Marshal.GetLastWin32Error();
int lastError = Kernel32.GetLastError();
Kernel32.CloseHandle(existingTokenHandle);
throw new Exception("DuplicateToken Failed: " + lastWin32Error + " - " + lastError);
}
// create an identity from the token
WindowsIdentity newId = new WindowsIdentity(duplicateTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
return impersonatedUser;
}
finally
{
//free all handles
if (existingTokenHandle != IntPtr.Zero)
{
Kernel32.CloseHandle(existingTokenHandle);
}
if (duplicateTokenHandle != IntPtr.Zero)
{
Kernel32.CloseHandle(duplicateTokenHandle);
}
}
}
Otros consejos
Después de esto yo no soy capaz de utilizar el identidad suplantada
La suplantación debe ser eficaz para el acceso en la misma caja, pero no en la red.
Puede ser, como se muestra en el código de consultutah, que sólo tiene que llamar DuplicateToken () con el fin de convertir el símbolo de conexión a un testigo de suplantación antes de que pueda ser utilizado.
Creo que esto se debe a que es igual impersonatedUser.ImpersonationLevel suplantación.
Si tiene que actuar como el usuario suplantado a otros sistemas, es necesario un mayor nivel de suplantación denominado 'delegación'. Esto es básicamente equivalente a tener la contraseña del usuario para que pueda representarse a sí mismo como a otros.