2009-03-31 3 views
3

Ich brauche Zugriff auf die Dateien und Verzeichnisse, auf die das aktuelle IPrincipal über die Methoden Directory.GetDirectories() und Directory.GetFiles() zugreifen kann, ohne die anderen Dateien aufzulisten. Der Prozess selbst wird als NETWORK SERVICE ausgeführt, sodass er für die Dauer dieser Aufrufe den Principal für den aktuellen Benutzer (über IPrincipal) ändern muss.Datei- und Verzeichnissicherheit mit IPrincipal

Ich habe versucht, Thread.CurrentPrincipal zu dem neuen IPrincipal vor dem Dateizugriffsabschnitt zu ändern, aber es scheint keinen Unterschied zu machen.

Gibt es noch etwas, das ich tun kann, oder fehlt mir etwas?

+0

Ich denke, Sie finden es IPrincipal –

Antwort

5

Der Windows-Identitätswechsel löst dieses Problem, indem die Anmeldeinformationen zum Abrufen eines Benutzer-Tokens verwendet werden. Mit diesem Token kann dann eine WindowsIdentity abgerufen werden, die dann zum Generieren eines Identitätswechselkontexts verwendet wird. Innerhalb dieses Kontextbereichs können Sie dann auf das Dateisystem als den imitierten Benutzer zugreifen.

Natürlich müssen Sie den Benutzernamen und das Kennwort speichern, damit dieser Ansatz funktioniert.

Zunächst definieren Sie die Windows-APIs benötigt, um ein Benutzertoken von Windows zu erhalten:

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); 
} 

Dann diese APIs verwenden, um ein Windows aquire:

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); 
} 

Und schließlich nutzen diese Identität zu einen Identitätswechsel Kontext erzeugen:

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; 
    } 
} 

Schließlich ist es wichtig zu bereinigen, die Windows-Handle mit dem IDisposable-Muster, mit dem gespeicherten _userToken:

if (_userToken != IntPtr.Zero) 
    WindowsAPI.CloseHandle(_userToken); 
0

Ich glaube nicht, dass du das richtig machst. Sie sollten versuchen, Identitätswechsel zu verwenden. Schauen Sie sich zum Beispiel this Tutorial an, wie man das macht.

-1

Sie können DllImport und die Win32-API LogonUser verwenden, um sich als ein anderer Benutzer auszugeben.