首页 > 解决方案 > PasswordBox PasswordHelper 多重绑定

问题描述

在 WPF 中 a 的Password属性PasswordBox不是 aDependencyProperty所以我不能直接绑定到它。作为一种解决方法,我PasswordHelperhttps://www.wpftutorial.net/PasswordBox.html使用它,它附加了 aPasswordHelper.Password以便PasswordBox我可以绑定到它。

为了防止密码DataContext以纯文本形式存在,我想使用一个转换器,它会在将密码保存到DataContext. 因为我需要将 salt 和 salted hash 都保存到DataContext我正在使用的 aMultiBinding和 aIMultiValueConverter转换器StringToSaltedHashConverter中。

Password的问题是当我填写. 我已经检查了 Snoop 并且和的属性都根据我输入的内容而变化。我也被调用,我正在返回正确的值。PasswordSaltDataContextPasswordBoxPasswordPasswordHelper.PasswordPasswordBoxStringToSaltedHashConverter

我在这个表单上有一些其他的绑定(用户名、名字、姓氏、性别......),它们都可以正常工作。这是唯一不更新的。

¿ 为什么我DataContext没有得到更新?

XAML:

<PasswordBox x:Name="Password"
             Style="{DynamicResource PasswordBoxStyle1}"
             local:PasswordHelper.Attach="True">
    <local:PasswordHelper.Password>
        <MultiBinding Converter="{StaticResource StringToSaltedHashConverter}"
                      Mode="OneWayToSource">
            <Binding Path="Password" />
            <Binding Path="PasswordSalt" />
        </MultiBinding>
    </local:PasswordHelper.Password>
</PasswordBox>

后面的代码:

public class StringToSaltedHashConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        string str = value as string;
        string salt = Hash.CreateSalt();
        string hash = Hash.CreateHash(str, salt);
        object[] vs = { hash, salt };
        return vs;
    }
}

标签: wpfmultibindingpasswordboximultivalueconverter

解决方案


这不是要走的路。PasswordHelper班级和他们的喜欢应该被禁止上网。该PasswordBox.Password属性不可绑定有一个很好的理由,这是有据可查的。访问此属性将创建一个纯文本string表示,可以使用免费工具(例如 Microsoft Process Explorer)轻松检索该表示。

当您获得 Password 属性值时,您将密码作为纯文本公开在内存中。要避免这种潜在的安全风险,请使用 SecurePassword 属性以 SecureString 形式获取密码。

将此属性设置为 null 会导致基础密码设置为空。

您甚至将纯盐值存储在内存中 - 我真的希望这既不是商业应用程序也不是公共应用程序。您完全无法控制垃圾收集器何时从内存中删除任何值。由于String是不可变类型,因此用户密码的多个副本很可能会在内存中保持公开。

在 Windows 环境中推荐的身份验证是使用 Windows 用户身份验证 API。

您至少应该PasswordBox.Password通过设置它来清除该属性null

不应在视图中进行加密。

请编写负责任的代码!用户数据不是您的数据!

主窗口.xaml

<Window>
  <Window.DataContext>
    <ViewModel />
  </Window.DataContext>

  <PasswordBox x:Name="PasswordBox" />
</Window>

主窗口.xaml.cs

public partial class MainWindow : Window
{
  public MainWindow()
  {
    InitializeComponent();

    this.PasswordBox.PasswordChanged += OnPasswordChanged;
  }

  private void OnPasswordChanged(object sender, RoutedEventArgs e)
  {
    (this.DataContext as ViewModel).Password = this.PasswordBox.SecurePassword;
  }
}

视图模型.cs

pucblic class ViewModel
{
  private Model Model { get; }

  private SecureString password;
  public SecureString Password
  {
    private get => this.password;
    public set
    {
      this.password = value;
      OnPasswordChanged();
    }
  }

  private void OnPasswordChanged()
  {
    // Hash password in the model e.g. to compare it to a hashed database value
    this.Model.TryLogin(this.Password);
  }
}

模型.cs

public class Model
{
  public bool TryLogin(SecureString password)
  {  
    IntPtr unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(password);
    string hashedPassword = HashPassword(Marshal.PtrToStringUni(unmanagedString));

    return PasswordIsValid(hashedPassword);
  }

  private string HashPassword(string unsecurePassword)
  {
    // Hash algorithm
  }
}

推荐阅读