4

Nov

WPF & Passwords

 

Ciao a tutti

 

WPF sappiamo è un framework di sviluppo per applicazioni con grafica ricca, volendo altamente 3D, e con un modello di eventi e di binding innovativo

 

Capita spesso di realizzare applicazioni che fanno uso di una login con il classico Username e Password da digitare

Benchè le applicazioni WPF usino particolarmente bene il pattern MVVM per associare grafica e logica, non è una buona idea mettere in una variabile di tipo ViewModel questa coppia di dati in chiaro.

Il mio consiglio è fare a meno di MVVM in questo caso, e usare un paio di accortezze importanti come property private e SecureString.

Io ad esempio, nella vista di login, setto semplicemente in un evento (il click del Login) le due proprietà chiave (username, password) in 2 proprietà di un a classe statica appositamente creata:

void LoginButton_Click(object sender, RoutedEventArgs e)
{
    Globals.LoggedUsername = Username.Text;
    Globals.LoggedPassword = Password.SecurePassword;
    Password.Password = string.Empty;
}

Username è una proprietà classica, mentre Password, espone in maniera pubblica il solo setter (writeonly in VB)

public static string LoggedUsername { get; set;}
public static SecureString LoggedPassword { private get; set;}

Potete notare che in WPF ho usato un controllo PasswordBox per far digitare all’utente la password, così da averne già la rappresentazione in SecureString, una stringa immutabile, come le classiche stringhe del .NET, con in più la crittografia inclusa in memoria (in pratica non può essere dumpata a differena di tutte le altre variabili, string incluse)

Questo farà si che l’unico istante in cui sarà presente nella memoria dell’applicazione la password in chiaro (garbage collection permettendo), sarà l’attimo tra cui l’utente la digita e preme il pulsante di login che infatti ha anche il compito di ripulire il controllo PasswordBox che contiene anche la password in chiaro, lasciando di fatto come unica password quella crittata (SecureString) contenuta nella classe Globals, appositamente creata.

La stessa classe statica mette poi a disposizione del resto dell’applicazione un metodo per avere un istanza di proxy di servizio per contattare il BackEnd con la logica.

public static Services.MyService GetFatturaZeroService()
{
    var pwd = System.Runtime.InteropServices.Marshal.PtrToStringUni(System.Runtime.InteropServices.Marshal.SecureStringToBSTR(LoggedPassword));
    var c = new Services.MyService("MyConfigurationName");
    c.ClientCredentials.UserName.UserName = LoggedUsername;
    c.ClientCredentials.UserName.Password = pwd;
    return c;
}

Qui, come vediamo, è presente il codice per leggere di nuovo in chiaro la password, così facendo ancora per 1 altro attimo sarà presente nell’area di memoria della nostra app la password in chiaro, ma come sempre, programmare in modo sicuro non significa annullare i rischi, significa ridurre la superficie di attacco… in poche parole, non mostrare il fianco

 

a presto

by Antonio Esposito on 11/4/2011