How to bind to a PasswordBox in MVVM
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
PasswordBox and MVVM
Personally I just pass the entire PasswordBox
control to my LoginCommand
I know it breaks MVVM because the ViewModel layer now references a View-specific object, but I think in this specific case it's OK.
So I might have XAML that looks like this:
<Button Content="Login"
Command="{Binding LoginCommand}"
CommandParameter="{Binding ElementName=MyPasswordBox}" />
And a LoginCommand
that does something like this:
private void Login(object obj)
{
PasswordBox pwBox = obj as PasswordBox;
SomeBlackBoxClass.ValidatePassword(UserName, pwBox.Password);
}
I suppose you could also run some kind of encryption algorithm on the value and compare the hash of that value to the hash of the user's password too
private void Login(object obj)
{
PasswordBox pwBox = obj as PasswordBox;
var encryptedPassword = SomeLibrary.EncryptValue(pwBox.Password, someKey);
if (encryptedPassword == User.EncryptedPassword)
// Success
}
I'm no expert on the PasswordBox
control or security, but I do know that you don't want to be storing the user's password in plain text anywhere in memory within your application
(Technically, it's stored as plain text in PasswordBox.Password
- you can use something like Snoop to verify this if you want - however typically the PasswordBox doesn't exist for longer than it takes the user to login, and the actual "password" is just text entered by the user, which may or may not be correct. A keylogger could get you the same information.)
WPF MVVM PasswordBox Binding
You simply can't set the SecurePassword. It is a readOnly Property. If you want to fill the PasswordBox, you have to set the Unsecure String Password Property.
Bind a WPF passwordbox
The Password
property is not a dependency property -- for security reasons. You can easily get the plain-text password, though.
XAML:
<PasswordBox
x:Name="passwordBox"
PasswordChanged="OnPasswordChanged" />
Code-behind event handler:
private void OnPasswordChanged(
object sender,
RoutedEventArgs e)
{
Debug.WriteLine(passwordBox.Password);
}
Updates
- Samuel Jack describes how to bind to a
PasswordBox
using attached properties - A discussion on security risk
PasswordBox Binding
Interesting.
look at this blog post and see if it is helping you.
http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html
Apparently the link is dead now so here is the original solution (found here):
You can use attached properties to create a helper like this:
public static class PasswordHelper
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached("Password",
typeof(string), typeof(PasswordHelper),
new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
public static readonly DependencyProperty AttachProperty =
DependencyProperty.RegisterAttached("Attach",
typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, Attach));
private static readonly DependencyProperty IsUpdatingProperty =
DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
typeof(PasswordHelper));
public static void SetAttach(DependencyObject dp, bool value)
{
dp.SetValue(AttachProperty, value);
}
public static bool GetAttach(DependencyObject dp)
{
return (bool)dp.GetValue(AttachProperty);
}
public static string GetPassword(DependencyObject dp)
{
return (string)dp.GetValue(PasswordProperty);
}
public static void SetPassword(DependencyObject dp, string value)
{
dp.SetValue(PasswordProperty, value);
}
private static bool GetIsUpdating(DependencyObject dp)
{
return (bool)dp.GetValue(IsUpdatingProperty);
}
private static void SetIsUpdating(DependencyObject dp, bool value)
{
dp.SetValue(IsUpdatingProperty, value);
}
private static void OnPasswordPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
passwordBox.PasswordChanged -= PasswordChanged;
if (!(bool)GetIsUpdating(passwordBox))
{
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += PasswordChanged;
}
private static void Attach(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
if (passwordBox == null)
return;
if ((bool)e.OldValue)
{
passwordBox.PasswordChanged -= PasswordChanged;
}
if ((bool)e.NewValue)
{
passwordBox.PasswordChanged += PasswordChanged;
}
}
private static void PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
}
Use it:
<PasswordBox w:PasswordHelper.Attach="True"
w:PasswordHelper.Password="{Binding Text, ElementName=plain, Mode=TwoWay}"
Width="100"/>
MVVM, Behavior and passwordBox
Just moved class PasswordBehavior into view code behind and create Property "Password" in VM:
private string _Password;
public string Password
{
get { return _Password; }
set { _Password = value; NotifyPropertyChanged("Password"); }
}
All works as expected.
PasswordBox with MVVM
For security reasons the Password property is not a dependency property and therefore you can't bind to it. Unfortunately you'll need to perform the binding in the code behind the old fashioned way (register for OnPropertyChanged event and update the value through code...)
I quick search brings me to this blog post which shows how to write an attached property to sidestep the issue. Whether this is worth doing or not though really depends on your aversion to code-behind.
How to bind to a PasswordBox in MVVM
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
Related Topics
Transparent Control Over Picturebox
How to Perform a Left Outer Join Using Linq Extension Methods
How to Bind to a Passwordbox in Mvvm
Difference Between Null and System.Dbnull.Value
Convert Json String to C# Object
Most Efficient Way to Randomly "Sort" (Shuffle) a List of Integers in C#
How to Do Constructor Chaining in C#
Display Lines Number in Stack Trace For .Net Assembly in Release Mode
Append Lines to a File Using a Streamwriter
Comparing Two Byte Arrays in .Net
Difference Between Shadowing and Overriding in C#
Color Different Parts of a Richtextbox String
Deciding Between Httpclient and Webclient
How to Create Linq Expression Tree to Select an Anonymous Type
How to Associate a File Extension to the Current Executable in C#
C# Error: "An Object Reference Is Required For the Non-Static Field, Method, or Property"