c# - 如何绑定(bind)到 MVVM 中的密码框

标签 c# wpf mvvm wpf-controls passwords

我在绑定(bind)到 PasswordBox 时遇到了问题。这似乎是一个安全风险,但我正在使用 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 包含来 self 的数据 ViewPasswordNull|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

最佳答案

也许我遗漏了什么,但似乎大多数这些解决方案都使事情过于复杂并且取消了安全实践。

该方法不违反MVVM模式,保持了完全的安全性。是的,从技术上讲它是代码隐藏的,但它只不过是一个“特例”绑定(bind)。 ViewModel 仍然不知道 View 实现,在我看来,如果您尝试将 PasswordBox 传递给 ViewModel,它就会这样做。

Code Behind != 自动违反 MVVM。这完全取决于你用它做什么。在这种情况下,我们只是手动编写绑定(bind)代码,所以它都被视为 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 属性。像这样:

( View 模型属性)

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 的接口(interface)替换(动态)转换。但实际上,“普通”数据绑定(bind)也不是强类型的,所以没什么大不了的。

private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
    if (this.DataContext != null)
    { ((IMyViewModel)this.DataContext).Password = ((PasswordBox)sender).Password; }
}

最重要的是 - 您的密码是安全的,您的 ViewModel 与任何其他属性一样只有一个属性,并且您的 View 是自包含的,不需要外部引用。

关于c# - 如何绑定(bind)到 MVVM 中的密码框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1483892/

相关文章:

c# - Windows 手机 : How to get list of installed applications & install/remove applications remotely

c# - 如何从服务器端代码反序列化 JSON

c# - 我如何对 wpf 应用程序中从 sleep 模式唤醒的窗口使用react?

WPF Datagrid - 添加和删除行和 MVVM

mvvm - KendoUI - 使用 MVVM 和远程数据时的级联下拉列表

c# - 在控制台应用程序中解析粘贴的文本

c# - 如何覆盖 TextBox 文本属性

c# - MVVM模式是否适合此应用程序的要求?

wpf - 如何在MVVM中实现分页?

c# - 更新目标触发器