如何绑定到MVVM中的密码箱
我遇到了绑定到密码框的问题。 看起来这是一个安全风险,但我使用MVVM模式,所以我想绕过这个。 我在这里找到了一些有趣的代码(有没有人使用过这个或类似的东西?)
http://www.wpftutorial.net/PasswordBox.html
它在技术上看起来不错,但我不确定如何检索密码。
我基本上在我的LoginViewModel
Username
和Password
属性。 Username
很好,并且正在工作,因为它是一个TextBox
。
我使用上面的代码,并输入了这个
<PasswordBox ff:PasswordHelper.Attach="True"
ff:PasswordHelper.Password="{Binding Path=Password}" Width="130"/>
当我将PasswordBox
作为TextBox
和Binding Path=Password
,我的LoginViewModel
的属性被更新了。
我的代码非常简单,基本上我的Button
有一个Command
。 当我按下它时, CanLogin
被调用,如果它返回true,它会调用Login
。
你可以看到我检查我的财产的Username
,这很好。
在Login
我向我的服务发送Username
和Password
, Username
包含我的View
中的数据,但Password
为Null|Empty
private DelegateCommand loginCommand;
public string Username { get; set; }
public string Password { get; set; }
public ICommand LoginCommand
{
get
{
if (loginCommand == null)
{
loginCommand = new DelegateCommand(
Login, CanLogin );
}
return loginCommand;
}
}
private bool CanLogin()
{
return !string.IsNullOrEmpty(Username);
}
private void Login()
{
bool result = securityService.IsValidLogin(Username, Password);
if (result) { }
else { }
}
这就是我正在做的
<TextBox Text="{Binding Path=Username, UpdateSourceTrigger=PropertyChanged}"
MinWidth="180" />
<PasswordBox ff:PasswordHelper.Attach="True"
ff:PasswordHelper.Password="{Binding Path=Password}" Width="130"/>
我有我的TextBox
,这是没有问题的,但在我的ViewModel
, Password
是空的。
我做错了什么或缺少一个步骤?
我放了一个断点,并确信代码进入静态助手类,但它永远不会更新我的ViewModel
Password
。
对不起,但你做错了。
人们应该在他们的眼皮内侧刺上以下安全指引:
切勿将纯文本密码保存在内存中。
WPF / Silverlight PasswordBox不公开DP密码属性的原因是安全相关的。
如果WPF / Silverlight要保留密码的DP,则需要框架将密码本身在内存中加密。 这被认为是相当麻烦的安全攻击媒介。 PasswordBox使用加密的内存(各种),并且访问密码的唯一方法是通过CLR属性。
我建议在访问PasswordBox.Password CLR属性时,不要将它放在任何变量中或作为任何属性的值。
在客户端机器RAM上以明文形式保存密码是一种安全禁止。
所以摆脱那个“公共字符串密码{get; set;}”你已经到了那里。
在访问PasswordBox.Password时,只需将其取出并尽快将其发送到服务器即可。 不要保持密码的价值,不要像处理任何其他客户端机器文本那样对待它。 不要在内存中保留明确的文本密码。
我知道这打破了MVVM模式,但你永远不应该绑定到PasswordBox.Password附加DP,将你的密码存储在ViewModel或任何其他类似的恶作剧。
如果你正在寻找一个超架构的解决方案,那么这里有一个:
1.使用返回密码明文的一种方法创建IHavePassword接口。
2.让你的UserControl实现一个IHavePassword接口。
3.将您的IoC的UserControl实例注册为实现IHavePassword接口。
4.当需要您的密码的服务器请求发生时,请致电您的IoC以获取IHavePassword实现,并且只能获得令人垂涎的密码。
只是我的承担。
- 贾斯汀
我的2美分:
我使用WPF和MVVM开发了一次典型的登录对话框(用户和密码框,加上“确定”按钮)。 我通过简单地将密码箱控件本身作为参数传递给附加到“确定”按钮的命令来解决密码绑定问题。 所以在我看来:
<PasswordBox Name="txtPassword" VerticalAlignment="Top" Width="120" />
<Button Content="Ok" Command="{Binding Path=OkCommand}"
CommandParameter="{Binding ElementName=txtPassword}"/>
在ViewModel中,附加命令的Execute
方法如下所示:
void Execute(object parameter)
{
var passwordBox = parameter as PasswordBox;
var password = passwordBox.Password;
//Now go ahead and check the user name and password
}
这稍微违反了MVVM模式,因为现在ViewModel知道如何实现View,但是在那个特定的项目中我可以负担得起。 希望这对其他人也有用。
也许我错过了一些东西,但是似乎大部分这些解决方案都会让事情变得复杂并放弃安全实践。
此方法不违反MVVM模式并保持完整的安全性。 是的,从技术上来说它是代码隐藏,但它不过是一种“特殊情况”绑定。 ViewModel仍然不知道视图实现,如果你试图将密码框传递给视图模型,这在我看来就是这样。
Code Behind!=自动MVVM违规。 这完全取决于你用它做什么。 在这种情况下,我们只是手动编码一个绑定,所以它被认为是UI实现的一部分,因此是可以的。
在ViewModel中,只是一个简单的属性。 我将它定义为“只写”,因为不应该有任何理由需要从ViewModel外部检索它,但它不一定是。 请注意,它是一个SecureString,而不仅仅是一个字符串。
public SecureString SecurePassword { private get; set; }
在xaml中,您设置了一个PasswordChanged事件处理程序。
<PasswordBox PasswordChanged="PasswordBox_PasswordChanged"/>
在后面的代码中:
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
if (this.DataContext != null)
{ ((dynamic)this.DataContext).SecurePassword = ((PasswordBox)sender).SecurePassword; }
}
使用这种方法,您的密码始终保持在SecureString中,因此可以提供最大的安全性。 如果您真的不关心安全问题,或者需要明文密码用于需要它的下游方法(注意:大多数需要密码的.NET方法也支持SecureString选项,因此您可能并不需要明文密码即使你认为你这样做),你也可以直接使用Password属性。 喜欢这个:
(ViewModel属性)
public string Password { private get; set; }
(代码后面)
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
if (this.DataContext != null)
{ ((dynamic)this.DataContext).Password = ((PasswordBox)sender).Password; }
}
如果你想保持强类型的东西,你可以用你的ViewModel的接口替换(动态)类型。 但是,实际上,“正常”的数据绑定也不是强类型的,所以它不是那么重要。
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
if (this.DataContext != null)
{ ((IMyViewModel)this.DataContext).Password = ((PasswordBox)sender).Password; }
}
所以最好的世界 - 你的密码是安全的,你的ViewModel只是有一个像任何其他属性一样的属性,并且你的View是自包含的,不需要外部引用。
链接地址: http://www.djcxy.com/p/44651.html