【问题标题】:Using PasswordBox with WPF - MVVM在 WPF 中使用 PasswordBox - MVVM
【发布时间】:2010-08-09 21:57:15
【问题描述】:

我已经阅读了几篇关于如何使用附加属性绑定到 WPF 中 PasswordBox 的值的文章。但是,每篇文章也都引用了 .NET 文档,该文档解释了为什么 PasswordBox 一开始就不能绑定。

我不认为自己是安全专家,但我认为 Microsoft 的某个人知道他们在做什么,我不应该付出努力试图撤销它。

因此,我想出了自己的解决方案。

public class LoginViewModel
{
   // other properties here

   public PasswordBox Password
   {
      get { return m_passwordBox; }
   }

   // Executed when the Login button is clicked.
   private void LoginExecute()
   {
      var password = Password.SecurePassword;

      // do more stuff...
   }
}

然后,在我的 XAML 中,我只是通过将 Password 字段绑定到 ContentPresenter 来呈现 PasswordBox。

所以我的问题是……这样做有问题吗?我意识到通过让实际控件出现在我的 ViewModel 中,我在某种程度上破坏了 MVVM,但至少这似乎比不保护密码字段更正确。

如果这实际上是一个问题,是否有人提出了不涉及使用附加属性并将密码存储在 ViewModel 中的解决方案?

谢谢! -J

【问题讨论】:

  • 附加属性方法到底有什么问题?属性类型是字符串吗?为什么不让它成为 SecureString?
  • 就像我上面说的,它似乎有一个原因,它不是一个 DependencyProperty 开始,所以找到一个变通方法似乎是错误的方法。我想我可以轻松地“绑定”到 SecurePassword 属性。
  • Password 属性可绑定的问题是:它的值很容易被外部软件跟踪。比如 SNOOP。那么窃取你的密码是多么容易。
  • 想解释一下 ContentPresenter 吗?
  • @ktutnik 我知道这是一个老生常谈的问题,但只要我可以输入密码,开始窥探,聚焦密码框,检查密码属性并看到明文结果,我就不会不要专注于这个问题——如果你问我,拥有房产而不是 DP 的额外安全性并不能证明使用它时的匆忙。

标签: wpf security mvvm


【解决方案1】:

至少在登录期间需要密码时将密码存储在 VM 中有什么问题?您是正确的,根据 MVVM 模式,VM 不应该引用像 PasswordBox 这样的控件。

在视图中,为 PasswordChanged 事件添加一个处理程序。在处理程序中,使用密码框的 SecurePassword 更新 VM 中的 SecureString 属性。

【讨论】:

  • 如上所述,我不是安全专家,我只是尽力遵循文档中列出的指导方针。但是,与字符串相比,保留对 SecureString 的内存引用是否存在任何风险?看起来如果这不是问题,那么直接绑定到它就是框架的一部分。
  • 为什么 PasswordBox 的 Password 属性不是 DP 的原因在这里由微软的人解释:social.msdn.microsoft.com/forums/en-US/wpf/thread/…。我想新的 SecurePassword 属性不是 DP 是因为他们担心如果有人数据绑定到它并且在登录后忘记清除它,它将被锚定在内存中。但这只是猜测。
  • 感谢您的回复。有没有登录后“清零”的方法,这样我可以保证登录页面消失后该值不在内存中?
  • 好的,呃...我刚开始修改 API,并意识到 SecureString 上有一个 Clear 方法。我想这就是我要找的东西? TIA -J
  • 我的解决方案最终变成了一个大杂烩,但正是这个想法让我开始了。本质上,我创建了一个附加属性,它允许我绑定到 SecurePassword 属性。感谢您的意见!
【解决方案2】:

仅供参考,希望对您有所帮助。

  1. 我认为不要将密码设置为 DP,因为它很容易被 SNOOP 等外部软件跟踪。
  2. 对视图模型的依赖越少,代码就越好。它将帮助您进行单元测试和升级或更改(如果将来您想使用第三方密码框,您会怎么做?)
  3. 明智地使用“代码背后无用”的状态。

在您的代码中考虑这一点:

void loginButton_Clicked(object s, EventArgs e)
{
    myViewModel.Password = txPwdBox.Password;
    myViewModel.Login();
}

【讨论】:

  • 我忘了.. 你应该使用 View-First 方法来做到这一点。
【解决方案3】:

我喜欢你的想法。

是的,您在这里违反了 ViewModel 最佳实践,但是

  • 最佳做法是“在大多数情况下都行之有效的建议”,而不是严格的规则和
  • 编写简单、易读、可维护的代码并避免不必要的复杂性也是这些“最佳实践”规则之一(“附加属性”解决方法可能会稍微违反这些规则)。

在这里打破 View/ViewModel 障碍是否会成为您的问题取决于为什么您首先使用 ViewModel(例如,关注点分离、单元测试、可重用性),所以我无法回答。

【讨论】:

    【解决方案4】:

    我的 2 美分:

    在视图模型中加密密码,使用附加属性,并使用 ValueConverter 加密/解密密码。有了这个,即使有人使用 snoop,他们看到的只是加密数据。

    让我们知道什么最适合您的情况

    【讨论】:

      猜你喜欢
      • 2013-03-01
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多