2010-02-16 5 views
8

Ich habe ein Programm, das System.DirectoryServices.AccountManagement.PrincipalContext verwendet, um zu überprüfen, ob die Informationen, die ein Benutzer in einem Einrichtungsbildschirm eingegeben hat, ein gültiger Benutzer in der Domäne sind (der Computer selbst ist nicht auf der Domäne) und führen einige Operationen für die Benutzer der Domäne aus. Das Problem ist, dass der Benutzer nicht jedes Mal, wenn er das Programm ausführt, sein Kennwort eingeben muss, damit ich es speichern kann, aber ich fühle mich nicht wohl dabei, das Kennwort als Nur-Text in der Datei app.config zu speichern. PrincipalContext benötigt ein Klartext-Passwort, so dass ich keinen gesalzenen Hash machen kann, wie es von allen zum Speichern von Passwörtern empfohlen wird.Was kann ich tun, wenn Sie ein Kennwort nicht als Hash speichern können?

Dies ist, was ich tat

const byte[] mySalt = //It's a secret to everybody. 
[global::System.Configuration.UserScopedSettingAttribute()] 
public global::System.Net.NetworkCredential ServerLogin 
{ 
    get 
    { 
     var tmp = ((global::System.Net.NetworkCredential)(this["ServerLogin"])); 
     if(tmp != null) 
      tmp.Password = new System.Text.ASCIIEncoding().GetString(ProtectedData.Unprotect(Convert.FromBase64String(tmp.Password), mySalt, DataProtectionScope.CurrentUser)); 
     return tmp; 
    } 
    set 
    { 
     var tmp = value; 
     tmp.Password = Convert.ToBase64String(ProtectedData.Protect(new System.Text.ASCIIEncoding().GetBytes(tmp.Password), mySalt, DataProtectionScope.CurrentUser)); 
     this["ServerLogin"] = value; 
    } 
} 

War dies das Richtige zu tun oder gibt es einen besseren Weg?

EDIT - Hier ist eine aktualisierte Version basierend auf jedem Vorschlag

private MD5 md5 = MD5.Create(); 

[global::System.Configuration.UserScopedSettingAttribute()] 
public global::System.Net.NetworkCredential ServerLogin 
{ 
    get 
    { 
     var tmp = ((global::System.Net.NetworkCredential)(this["ServerLogin"])); 
     if(tmp != null) 
      tmp.Password = System.Text.Encoding.UTF8.GetString(ProtectedData.Unprotect(Convert.FromBase64String(tmp.Password), md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(tmp.UserName.ToUpper())), DataProtectionScope.CurrentUser)); 
     return tmp; 
    } 
    set 
    { 
     var tmp = value; 
     tmp.Password = Convert.ToBase64String(ProtectedData.Protect(System.Text.Encoding.UTF8.GetBytes(tmp.Password), md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(tmp.UserName.ToUpper())), DataProtectionScope.CurrentUser)); 
     this["ServerLogin"] = tmp; 
    } 
} 
+1

Wer und was Sie von Passwort zu verteidigen versuchen? – SLaks

+0

Ich würde sagen, "richtige" Art und Weise würde das Kerberos-Ticket behalten, aber ich weiß nicht, wie in diesem Zusammenhang, sorry. – ziya

+1

@Slaks - Ich verteidige das Passwort von gelangweilten Kollegen, die sich an den Computer eines anderen gesetzt haben. Ich möchte mich nur vor dem zufälligen Beobachter schützen, nicht vor einem entschlossenen Hacker. –

Antwort

2

Statt new System.Text.ASCIIEncoding() zu schreiben, sollten Sie System.Text.Encoding.ASCII schreiben.

Außerdem empfehle ich stattdessen UTF8.

Ansonsten sieht Ihr Code ziemlich gut aus.

+0

Danke für den Tipp über die andere Art, den Encoder zu verwenden. Warum empfiehlst du UTF8 über ASCII? –

+1

Damit Passwörter Unicode-Zeichen enthalten können. – SLaks

+0

Danke, ich werde es ändern. –

4

Für das Salz, würde ich eine Transformation auf den Benutzernamen (Hash) tun, anstatt das gleiche Salz für alle zu teilen.

Für so etwas würde ich auch nach einer Möglichkeit suchen, die vorhandene Sitzung länger am Leben zu erhalten, anstatt das Kennwort zu speichern, um neue Sitzungen zu erstellen.

+0

Die Sitzung ist die gesamte Instanz lebendig, die das Programm ausgeführt wird, ich muss nur die Sitzung mit dem Server erstellen, wenn das Programm gestartet wird, oder meinst du, die Sitzung zwischen Läufen lebendig zu halten? –

+0

Sie können einen Dienst oder ein anderes Hintergrundprogramm verwenden, um die Sitzung zu halten und länger am Leben zu halten. –

0

Ich mag den JoelCoehoorn-Ansatz.

Verwenden Sie einen Wert, der für den Benutzercomputer eindeutig ist, als das Kennwort "salt".

So wird es in jedem Deplyment anders sein;).

UPDATE: Siehe diesen Thread für Ideen: How-To-Get-Unique-Machine-Signature

+0

Wie meldet sich derselbe Benutzer an verschiedenen Maschinen an? Es muss pro Benutzer sein. –

+0

Hallo Joel danke für die Frage:) Wenn der Benutzer von PC zu PC wechseln: Er muss seine Domänen-Anmeldeinformationen erneut unbedingt vor dem Caching eingeben;) – SDReyes

+0

'ProtectedData.Protect' ist bereits pro Maschine. – SLaks

Verwandte Themen