„Personifikacja” w przestrzeni .NET zwykle oznacza uruchamianie kodu na określonym koncie użytkownika. Jest to nieco inna koncepcja niż uzyskanie dostępu do tego konta użytkownika za pomocą nazwy użytkownika i hasła, chociaż te dwa pomysły często się łączą. Opiszę je oba, a następnie wyjaśnię, jak używać mojej biblioteki SimpleImpersonation , która używa ich wewnętrznie.
Personifikacja
Interfejsy API do personifikacji są udostępniane w .NET za pośrednictwem System.Security.Principal
przestrzeni nazw:
Nowszy kod (.NET 4.6+, .NET Core itd.) Powinny zazwyczaj używają WindowsIdentity.RunImpersonated
, który akceptuje uchwyt do tokenu konta użytkownika, a następnie OSOBĄ Action
lub Func<T>
kodu do wykonania.
WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
});
lub
var result = WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
return result;
});
Starszy kod używał tej WindowsIdentity.Impersonate
metody do pobierania WindowsImpersonationContext
obiektu. Ten obiekt implementuje IDisposable
, więc generalnie powinien być wywoływany z using
bloku.
using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(tokenHandle))
{
// do whatever you want as this user.
}
Chociaż ten interfejs API nadal istnieje w .NET Framework, należy go zasadniczo unikać i nie jest dostępny w .NET Core ani .NET Standard.
Dostęp do konta użytkownika
Interfejs API do używania nazwy użytkownika i hasła w celu uzyskania dostępu do konta użytkownika w systemie Windows to LogonUser
- natywny interfejs API Win32. Obecnie nie ma wbudowanego interfejsu .NET API do jego wywoływania, więc należy uciec się do P / Invoke.
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
To jest podstawowa definicja połączenia, jednak należy wziąć pod uwagę znacznie więcej, aby faktycznie użyć jej w produkcji:
- Uzyskanie klamki z „bezpiecznym” wzorem dostępu.
- Odpowiednie zamykanie uchwytów natywnych
- Poziomy zaufania zabezpieczeń dostępu kodu (CAS) (tylko w .NET Framework)
- Przekazywanie,
SecureString
kiedy można bezpiecznie odebrać jeden za pomocą naciśnięć klawiszy użytkownika.
Ilość kodu do napisania, aby zilustrować to wszystko, przekracza to, co powinno być w odpowiedzi StackOverflow, IMHO.
Połączone i łatwiejsze podejście
Zamiast pisać to wszystko samodzielnie, rozważ użycie mojej biblioteki SimpleImpersonation , która łączy personifikację i dostęp użytkownika w jednym interfejsie API. Działa dobrze zarówno w nowoczesnych, jak i starszych bazach kodu, z tym samym prostym interfejsem API:
var credentials = new UserCredentials(domain, username, password);
Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
});
lub
var credentials = new UserCredentials(domain, username, password);
var result = Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
return something;
});
Zauważ, że jest bardzo podobny do WindowsIdentity.RunImpersonated
API, ale nie wymaga nic o uchwytach tokenu.
To jest interfejs API w wersji 3.0.0. Więcej informacji można znaleźć w pliku Readme projektu. Należy również zauważyć, że poprzednia wersja biblioteki korzystała z interfejsu API ze IDisposable
wzorcem, podobnym do WindowsIdentity.Impersonate
. Nowsza wersja jest znacznie bezpieczniejsza i obie są nadal używane wewnętrznie.