如何绑定到MVVM中的密码箱

我遇到了绑定到密码框的问题。 看起来这是一个安全风险,但我使用MVVM模式,所以我想绕过这个。 我在这里找到了一些有趣的代码(有没有人使用过这个或类似的东西?)

http://www.wpftutorial.net/PasswordBox.html

它在技术上看起来不错,但我不确定如何检索密码。

我基本上在我的LoginViewModel UsernamePassword属性。 Username很好,并且正在工作,因为它是一个TextBox

我使用上面的代码,并输入了这个

<PasswordBox ff:PasswordHelper.Attach="True"
    ff:PasswordHelper.Password="{Binding Path=Password}" Width="130"/>

当我将PasswordBox作为TextBoxBinding Path=Password ,我的LoginViewModel的属性被更新了。

我的代码非常简单,基本上我的Button有一个Command 。 当我按下它时, CanLogin被调用,如果它返回true,它会调用Login
你可以看到我检查我的财产的Username ,这很好。

Login我向我的服务发送UsernamePasswordUsername包含我的View中的数据,但PasswordNull|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 ,这是没有问题的,但在我的ViewModelPassword是空的。

我做错了什么或缺少一个步骤?

我放了一个断点,并确信代码进入静态助手类,但它永远不会更新我的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

上一篇: How to bind to a PasswordBox in MVVM

下一篇: How to bind inverse boolean properties in WPF?