如何从DevExpress WinForms TextEdit获取密码作为SecureString

时间:2011-02-01 05:49:39

标签: winforms security devexpress

WPF有PasswordBox接收密码输入到SecureString,但我有一个WinForms应用程序。我可以使用SecurePasswordTextBox,但我想要一些与DevExpress控件和DevExpress外观自定义混合的东西。在DevExpress TextEdit控件上,您可以设置UseSystemPasswordChar = true,但它不使用SecureString(并且不会:cf. 10/22/2010cf. also

如何轻松地将SecureString支持转换为DevExpress WinForms TextEdit控件?

我提出了一些问题,我将其作为自己的答案发布在下面。还有其他人有解决方案吗?

编辑:我接受我自己的答案,这是有效的,因为我需要DevExpress外观。

2 个答案:

答案 0 :(得分:1)

最简单的方法是使用在ElementHost中托管的WPF PasswordBox。

您可以从ToolBox中拖动ElementHost控件,或者在代码中执行整个操作:

public Form1()
{
    InitializeComponent();
    System.Windows.Forms.Integration.ElementHost host = new System.Windows.Forms.Integration.ElementHost();
    System.Windows.Controls.PasswordBox pb=new System.Windows.Controls.PasswordBox();
    host.Child =  pb;
    this.Controls.Add(host);
}

当然这不使用DevExpress控件,但是当有一个简单的替代方法时,我看不出有任何理由将Rich Text Editor用作密码框。

答案 1 :(得分:1)

这是我自己的答案:

而不是继承TextEdit,这似乎太复杂了,我只是抓住KeyPress事件并隐藏每个按下的字符,直到EditValueChanging事件。我在假字符串中保留了唯一的标记,以便我可以在每个EditValueChanging事件中找出我的SecureString中要更改的内容。

这是概念验证 - 一个带有TextEdit控件和两个事件处理程序的简单表单:

public partial class PasswordForm : DevExpress.XtraEditors.XtraForm
{
    private Random random = new Random();
    private HashSet<char> pool = new HashSet<char>();
    private char secret;
    private char token;
    private List<char> fake = new List<char>();

    public PasswordForm()
    {
        InitializeComponent();
        this.Password = new SecureString();
        for (int i = 0; i < 128; i++)
        {
            this.pool.Add((char)(' ' + i));
        }
    }

    public SecureString Password { get; private set; }

    private void textEditPassword_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
    {
        string value = e.NewValue as string;

        // If any characters have been deleted...
        foreach (char c in this.fake.ToArray())
        {
            if (value.IndexOf(c) == -1)
            {
                this.Password.RemoveAt(this.fake.IndexOf(c));
                this.fake.Remove(c);
                this.pool.Add(c);
            }
        }

        // If a character is being added...
        if (this.token != '\0')
        {
            int i = value.IndexOf(this.token);
            this.Password.InsertAt(i, this.secret);
            this.secret = '\0';
            fake.Insert(i, this.token);
        }
    }

    private void textEditPassword_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (Char.IsControl(e.KeyChar))
        {
            this.token = '\0';
        }
        else
        {
            this.token = this.pool.ElementAt(random.Next(this.pool.Count)); // throws ArgumentOutOfRangeException when pool is empty
            this.pool.Remove(this.token);
            this.secret = e.KeyChar;
            e.KeyChar = this.token;
        }
    }
}