问题 如何验证PasswordBox WPF


我正在尝试对a进行验证 PasswordBox。为了进行验证,我遵循了这一点 链接,这表明如何验证 TextBox

问题来了 PasswordBoxes。就像它一样 Password 由于安全原因,我无法绑定,我试图进行绑定 这个链接 (也解释说 这里,对于CodeProject用户)。

所以,显然,太棒了!我可以约束我的 PasswordBox 用它 Password 属性,那么我可以绑定我的验证。但它忽略了我......

这是一个常规的 TextBox 我使用和工作正常:

<local:ErrorProvider Grid.Column="1" Grid.Row="2" >
    <TextBox Width="160" 
          HorizontalAlignment="Left" 
           Name="textBoxUserPass" 
           Text="{Binding Path=Password, UpdateSourceTrigger=Explicit}" />
 </local:ErrorProvider>

这就是 PasswordBox 我试图模拟:

<local:ErrorProvider Grid.Column="1" Grid.Row="2" >
      <PasswordBox Width="160"
          HorizontalAlignment="Left"
          Name="textBoxUserPass"
          local:PasswordBoxAssistant.BindPassword="True"
          local:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, UpdateSourceTrigger=Explicit}" />
 </local:ErrorProvider>

这就是我得到的方式 BindingExpression 为每个人 TextBox

BindingExpression beUserName = textBoxUserName.GetBindingExpression(TextBox.TextProperty);
if (beUserName != null) beUserName.UpdateSource();

这就是我如何得到它 PasswordBox

BindingExpression bePassword = textBoxUserPass.GetBindingExpression(PasswordBoxAssistant.BoundPassword);
if (bePassword != null) bePassword.UpdateSource();

如果我们犯了任何错误(在我的Validation类中定义),当我这样做时:

if (!beUserName.HasError && !bePassword.HasError)

BindingExpression 应该说 真正 的  取决于错误验证。但对我来说 PasswordBox 从来没有得到价值......任何想法?


4959
2018-02-27 12:35


起源

你试过设置吗? ValidatesOnDataErrors=True 和 ValidatesOnExceptions=True 你的绑定? - Richard Deeming
它不存在 PasswordBox... - Sonhja
它适用于 BoundPassword 附属物: local:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, UpdateSourceTrigger=Explicit, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" - Richard Deeming
每个人似乎都在使用的PasswordBoxAssistant在哪里? - James
PasswordBoxAssistant: blog.functionalfun.net/2008/06/... - Charlie


答案:


尝试设置 ValidatesOnDataErrors=True 和 ValidatesOnExceptions=True 你的装订:

<PasswordBox ...
   local:PasswordBoxAssistant.BoundPassword="{Binding Path=Password,
      UpdateSourceTrigger=Explicit, 
      ValidatesOnDataErrors=True, 
      ValidatesOnExceptions=True}"
/>

11
2018-02-27 14:50





另一种解决方案是在中间没有使用任何“不安全”的字符串,而是调整Window代码,如下所示:

假设我有一个像这样的MVVM对象,使用WPF验证 IDataErrorInfo的

public class MyObject : INotifyPropertyChanged, IDataErrorInfo
{
    ...
    public SecureString SecurePassword
    {
        get
        { ... }
        set
        {
            ...
            OnPropertyChanged("SecurePassword");
        }
    }

    ...

    string IDataErrorInfo.Error { get { return Validate(null); } }
    string IDataErrorInfo.this[string columnName] { get { return Validate(columnName); } }

    private string Validate(string memberName)
    {
        string error = null;
        ...
        if (memberName == "SecurePassword" || memberName == null)
        {
            // this is where I code my custom business rule
            if (SecurePassword == null || SecurePassword.Length == 0)
            {
                error = "Password must be specified.";
            }
        }
        ...
        return error;
    }

}

还有一个带有PasswordBox的Window Xaml,如下所示:

<PasswordBox Name="MyPassword" PasswordChanged="MyPassword_Changed" ... />

然后,像这样的相应Window代码将触发PasswordBox绑定:

// add a custom DependencyProperty
public static readonly DependencyProperty SecurePasswordProperty =
    DependencyProperty.RegisterAttached("SecurePassword", typeof(SecureString), typeof(MyWindow));

public MyWindow()
{
    InitializeComponent();

    DataContext = myObject; // created somewhere

    // create a binding by code
    Binding passwordBinding = new Binding(SecurePasswordProperty.Name);
    passwordBinding.Source = myObject;
    passwordBinding.ValidatesOnDataErrors = true;
    // you can configure other binding stuff here
    MyPassword.SetBinding(SecurePasswordProperty, passwordBinding);
}

private void MyPassword_Changed(object sender, RoutedEventArgs e)
{
    // this should trigger binding and therefore validation
    ((MyObject)DataContext).SecurePassword = MyPassword.SecurePassword;
}

2
2018-05-15 17:01



我希望人们意识到PasswordBox本身是不安全的,因为它会愉快地解密任何要求很好的应用程序的密码。只需依附于流程,并通过反思,说“嘿PasswordBox,密码属性中有什么?”我知道你可以从内存抓取中获得一些保护,特别是避免将其存储在字符串字段中,但是对于大多数用例来说,它已经被游戏结束了 任何 恶意有效载荷已经安装 - 也许不是 真 值得烦恼的。 - Daniel
@Daniel - SecureString不能保护现场调试器或类似的实时威胁。这里处理威胁的一个很好的解释是: blogs.msdn.microsoft.com/shawnfa/2004/05/27/... (还要确保你阅读Shawn的评论) - Simon Mourier


据我所知,在PasswordBox上添加验证的唯一方法是在SecurePassword的绑定属性的setter中抛出一个新的ValidationException。 PasswordBoxAssistant对此没有帮助。


1
2018-02-27 13:49



你能提供一个例子或链接吗?这听起来像一个解决方案。 - Sonhja
这是我在我正在处理的旧应用程序中找到的:public SecureString NewPassword {get {return _newPassword; } set {_newPassword = value; string error = IsPasswordValid(); if(!string.IsNullOrEmpty(error)){throw new ValidationException(error); }}} - Cristian Chereches
嗯,要尝试一下,但确切的解决方案是Richard Deeming发布的(对于这个案例)。但是我也会尝试这个,因为我的代码也有这个特殊情况。 - Sonhja


在绑定上设置Mode = TwoWay

local:PasswordBoxAssistant.BoundPassword="{Binding Path=Password,Mode=TwoWay,
UpdateSourceTrigger=Explicit}"

1
2017-07-03 19:36