I have come across a problem with binding to a PasswordBox
. It seems it\'s a security risk but I am using the MVVM pattern so I wish to bypass this. I found som
Sorry, but you're doing it wrong.
People should have the following security guideline tattooed on the inside of their eyelids:
Never keep plain text passwords in memory.
The reason the WPF/Silverlight PasswordBox
doesn't expose a DP for the Password
property is security related.
If WPF/Silverlight were to keep a DP for Password
it would require the framework to keep the password itself unencrypted in memory. Which is considered quite a troublesome security attack vector.
The PasswordBox
uses encrypted memory (of sorts) and the only way to access the password is through the CLR property.
I would suggest that when accessing the PasswordBox.Password
CLR property you'd refrain from placing it in any variable or as a value for any property.
Keeping your password in plain text on the client machine RAM is a security no-no.
So get rid of that public string Password { get; set; }
you've got up there.
When accessing PasswordBox.Password
, just get it out and ship it to the server ASAP.
Don't keep the value of the password around and don't treat it as you would any other client machine text. Don't keep clear text passwords in memory.
I know this breaks the MVVM pattern, but you shouldn't ever bind to PasswordBox.Password
Attached DP, store your password in the ViewModel or any other similar shenanigans.
If you're looking for an over-architected solution, here's one:
1. Create the IHavePassword
interface with one method that returns the password clear text.
2. Have your UserControl
implement a IHavePassword
interface.
3. Register the UserControl
instance with your IoC as implementing the IHavePassword
interface.
4. When a server request requiring your password is taking place, call your IoC for the IHavePassword
implementation and only than get the much coveted password.
Just my take on it.
-- Justin
I used this method and passed the password box, although this does violate the MVVM it was essential for me because I was using a content control with data template for my login within my shell which is a complex shell enviroment. So accessing the code behind of the shell would have been crap.
Passing the passwordbox I would think is same as accessing control from code behind as far as I know. I agree passwords, dont keep in memory etc In this implementation I don't have property for password in view model.
Button Command
Command="{Binding Path=DataContext.LoginCommand, ElementName=MyShell}" CommandParameter="{Binding ElementName=PasswordBox}"
ViewModel
private void Login(object parameter)
{
System.Windows.Controls.PasswordBox p = (System.Windows.Controls.PasswordBox)parameter;
MessageBox.Show(p.Password);
}
For complete newbies like me, here is a complete working sample of what Konamiman
suggested above. Thanks Konamiman
.
<PasswordBox x:Name="textBoxPassword"/>
<Button x:Name="buttonLogin" Content="Login"
Command="{Binding PasswordCommand}"
CommandParameter="{Binding ElementName=textBoxPassword}"/>
public class YourViewModel : ViewModelBase
{
private ICommand _passwordCommand;
public ICommand PasswordCommand
{
get {
if (_passwordCommand == null) {
_passwordCommand = new RelayCommand<object>(PasswordClick);
}
return _passwordCommand;
}
}
public YourViewModel()
{
}
private void PasswordClick(object p)
{
var password = p as PasswordBox;
Console.WriteLine("Password is: {0}", password.Password);
}
}
I used an authentication check followed by a sub called by a mediator class to the View (which also implements an authentication check) to write the password to the data class.
It's not a perfect solution; however, it remedied my problem of not being able to move the password.
My 2 cents:
I developed once a typical login dialog (user and password boxes, plus "Ok" button) using WPF and MVVM. I solved the password binding issue by simply passing the PasswordBox control itself as a parameter to the command attached to the "Ok" button. So in the view I had:
<PasswordBox Name="txtPassword" VerticalAlignment="Top" Width="120" />
<Button Content="Ok" Command="{Binding Path=OkCommand}"
CommandParameter="{Binding ElementName=txtPassword}"/>
And in the ViewModel, the Execute
method of the attached command was as follows:
void Execute(object parameter)
{
var passwordBox = parameter as PasswordBox;
var password = passwordBox.Password;
//Now go ahead and check the user name and password
}
This slightly violates the MVVM pattern since now the ViewModel knows something about how the View is implemented, but in that particular project I could afford it. Hope it is useful for someone as well.
This works just fine for me.
<Button Command="{Binding Connect}"
CommandParameter="{Binding ElementName=MyPasswordBox}"/>