Benutzer Context innerhalb einer Anwendung ändern

Viele Entwickler haben immer wieder das Problem, dass man die Anwendung fertig entwickelt hat, und dann merkt, dass man Daten an Orte schreiben will, an denen der angegemeldete Benutzer keine Berechtigungen hat. Dies ist vor allem dann ein Problem, wenn die Benutzer ohne Administrative Berechtigungen (Was durchaus Sinn macht) arbeiten.

Um trotzdem die Daten an den entsprechenden Orten speichern zu können, gibt es unter C# die Möglichkeit von sogenannten "Impersonations". Dies bedeutet, man ändert zur Laufzeit den Benutzerkontext für gewisse Codebereiche.

Wie wird dies gemacht? Das ganze ist sehr einfach zu realisieren. Man benötigt lediglich einen Pointer auf ein Windows Logon Token. Dies erzeugt man über die API Funktion "LogonUser".

[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

IntPtr accessToken = IntPtr.Zero;

private void impersonationTest() {
  if (LogonUser("Benutzer","Domain","Passwort",2,0,accessToken) {
    ...
  } else {
    ...
    // Login nicht erfolgreich!
  }
}

Das erstellte Token kann dann an die WindowsIdentity Klasse übergeben werden, aus welcher dann ein neuer Kontext erstellt wird.

WindowsIdentity identity = new WindowsIdentity(accessToken);
WindowsImpersonationContext context = identity.Impersonate();
...
// Was man immer als andere Person machen will
...
context.Undo();

Mit der Methode Impersonate() wird der Kontext auf den neuen Benutzer gewechselt, und mit Undo() auf dem Kontextobjekt wird das ganze wieder rückgängig gemacht.

Hier das ganze Beispiel:

[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

IntPtr accessToken = IntPtr.Zero;

private void impersonationTest() {
  if (LogonUser("Benutzer","Domain","Passwort",2,0,accessToken) {
    WindowsIdentity identity = new WindowsIdentity(accessToken);
    WindowsImpersonationContext context = identity.Impersonate();
    ...
    // Hier den Code einfügen, welcher unter einem anderen Kontext laufen soll.
    ...
    context.Undo();
    context.Dispose();
    identity.Dispose();
  } else {
    ...
    // Login nicht erfolgreich!
  }
}