【问题标题】:Setting initial value of PasswordBox设置 PasswordBox 的初始值
【发布时间】:2015-08-19 07:35:04
【问题描述】:

我想知道 PasswordBox 控件涉及的所有安全性是否完全有可能:

我有一个 XAML 表单 (C#/WPF),用户将在其中配置数据库访问。在该表单中,我使用 PasswordBox 来获取 SQL Server 用户密码。

由于此数据已保存到磁盘以供将来使用(在受密码保护的 SQL Server CE 数据库文件中),在第一次运行时没有设置密码,如果用户返回并出于某种原因需要编辑 SQL 连接,那么可能会保留以前配置的密码(除非他使用 Windows 身份验证而不是 SQL 用户身份验证)

所以我想在第一次运行时显示一个空的 PasswordBox,但如果已经设置了密码,当用户返回时,我想显示 X 个“*”(以表明存在密码。

由于 PasswordBox.Password 不可绑定,我只能选择始终显示为空或始终显示固定数量的“*”(通过设置实际上不代表真实密码的默认密码)。

是否有任何替代方案(除了像 PasswordBox Helper 之类的注入绑定的东西 - 我宁愿不走那条路,因为我可能没有考虑让 MS 选择不使其可绑定甚至一个安全字符串)?

【问题讨论】:

  • @faflo10:是的,我将视图、视图模型和模型分开,但如果绝对需要,当然可以打破这些规则。从 SQLce 文件中读取的密码(如果有)保存在我的模型中,而 PasswordBox 位于视图中
  • 您可以从文件中读取并在后面写代码说明PasswordBox.Password = "ReadPassword";
  • PasswordBox 并不真正适合MVVM,但您可以编写附加行为来设置PasswordBox.SecurePassword(即SecureString)。此行为必须有权访问现有密码(在某些 User 类中再次作为 SecureString)或输入一些 fake 密码(但您可以简单地使用 PasswordBox.Password),例如User.IsLogged 已设置。
  • @MohitShrivastava - 今晚需要尝试那个 - 小心把它作为答案,以防它适用于我的用例并且我将它奖励给你?
  • @Sinatr 不正是我提到的作为我试图避免的 PasswordBox Helper 类的附加行为吗?如果不是,请详细说明作为答案?

标签: c# wpf wpf-controls passwordbox


【解决方案1】:

您可以从文件中读取密码。

//Storing the Password in String.
string pwd = "Password Read from the file";
PasswordBox.Password = pwd;

所以当应用程序第一次打开并且文件中没有任何密码时,它会显示空的 PasswordBox。再次,当用户已设置密码时,将在文件中找到密码,并将其加载到 PasswordBox 中。

【讨论】:

  • 这很有效 - 通过在模型中更改密码时使用从视图模型触发的事件。视图通过设置 PasswordBox 的值来响应该事件,并且 MVVM 保持不变 - 很好的答案。还应该使用 SecureString 而不是常规字符串将密码保存在模型中,以确保安全,而不是否定 PasswordBox 的安全功能
【解决方案2】:

您可以让 PasswordBox 具有此行为以在 MVVM 中启用绑定。

PasswordBoxBehavior.cs

public class PasswordBoxBehavior : Behavior<PasswordBox>
{
    public bool ResetPassword
    {
        get { return (bool)GetValue(ResetPasswordProperty); }
        set { SetValue(ResetPasswordProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ResetPassword.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ResetPasswordProperty =
        DependencyProperty.Register("ResetPassword", typeof(bool), typeof(PasswordBoxBehavior), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnResetPasswordChanged));

    static void OnResetPasswordChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        PasswordBoxBehavior behavior = depObj as PasswordBoxBehavior;
        PasswordBox item = behavior.AssociatedObject as PasswordBox;
        if (item == null)
            return;

        if ((bool)e.NewValue)
            item.Password = string.Empty;

        behavior.ResetPassword = false;
    }

    private bool isRoutedEventHandlerAssign;
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(PasswordBoxBehavior), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextChanged));

    static void OnTextChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        PasswordBoxBehavior behavior = depObj as PasswordBoxBehavior;
        PasswordBox item = behavior.AssociatedObject as PasswordBox;
        if (item == null)
            return;

        if (item.Password != e.NewValue as string)
        {
            item.Password = e.NewValue as string;
        }

        if (!behavior.isRoutedEventHandlerAssign)
        {
            item.PasswordChanged += (sender, eArg) =>
            {
                behavior.Text = item.Password;
            };
            behavior.isRoutedEventHandlerAssign = true;
        }
    }

    public PasswordBoxBehavior()
    {
    }
}

使用

<PasswordBox>
    <i:Interaction.Behaviors>
        <bh:PasswordBoxBehavior 
            Text="{Binding UserPassword}"
            ResetPassword="{Binding IsResetPassword}" />
    </i:Interaction.Behaviors>
</PasswordBox>

在哪里

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:bh="clr-namespace:<some namespace>;assembly=<some assembly>"

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-01-23
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多