繁体   English   中英

将文本保存到数组 C# 表单中

[英]Saving text into arrays C# forms

所以我试图在 C# 表单中创建一个用户名和密码系统,我有第二个表单用于创建您的帐户,您可以在其中输入您想要的用户名和相应的密码。 我有 2 个单独的数组,一个用于用户名,一个用于密码,我希望用户在用户名和密码的文本框中键入的任何内容都保存在各自的数组中,以便我可以将它们相互关联。 我将如何将文本框中写入的内容保存到数组中?

您可以使用 C# - Hashtable 代替数组

C# 在 System.Collections 命名空间中包含 Hashtable 集合,它类似于通用 Dictionary 集合。 Hashtable 集合存储键值对。 它通过计算每个键的哈希码并在内部将其存储在不同的存储桶中来优化查找,然后在访问值时匹配指定键的哈希码。 这是一个演示您想法的示例

using System;
using System.Collections;
using System.Collections.Generic;

Hashtable ht = new Hashtable();

protected void btnLogin_Click(object sender, EventArgs e)
{
    ht.Add(txtUserName.Text, txtPassword.Text);    
}

访问哈希表:

您可以使用索引器从哈希表中检索现有键的值。 请注意哈希表索引器需要一个键。

Hashtable ht = new Hashtable();

ht.Add(1, "One");
ht.Add(2, "Two");
ht.Add(3, "Three");
ht.Add(4, "Four");
ht.Add("Fv", "Five");
ht.Add(8.5F, 8.5F);

string strValue1 = (string)ht[2];
string strValue2 = (string)ht["Fv"];
float fValue = (float) ht[8.5F];

Console.WriteLine(strValue1);
Console.WriteLine(strValue2);
Console.WriteLine(fValue);

输出:

Two
Five
8.5 

C#中,当项目数已知并固定时,最好使用数组。 否则,一般List<T>就足以添加/删除项目。

我认为您要问的是如何为注册用户开发数据模型,以及如何使用 UI 与该模型进行交互。

这个谜题有几个部分:

1. 数据模型

从一个保存用户信息的类(下面的LoginUser )和一个保存授权用户列表的类(下面的UserRegistry )开始。

数据

添加方法以在 Xml 或您想要的任何存储中加载/保存用户注册表。 在下面的示例中,我使用内置的 XmlSerializer 从数据到文件并返回。

我的例子中的完整代码是

/// <summary>
/// The user registry.
/// </summary>
[Serializable()]
[XmlType(AnonymousType = true)]
[XmlRoot(ElementName = "Users", Namespace = "", IsNullable = false)]
public partial class UserRegistry
{

    public UserRegistry()
    {
        this.Users= new List<LoginUser>();
    }

    /// <summary>
    /// The list of users
    /// </summary>
    [XmlElement("User")]
    public List<LoginUser> Users { get; set; }

    /// <summary>
    /// Find the user in the list that matches the userId
    /// </summary>
    public LoginUser this[string userId]
    {
        get
        {
            return Users.FirstOrDefault((item) => item.UserId.ToLowerInvariant().Equals(userId.ToLowerInvariant()));
        }
    }

    public void Add(LoginUser user)
    {
        this.Users.Add(user);
    }
    /// <summary>
    /// Load a user list from an xml string.
    /// </summary>
    public static UserRegistry FromXml(string xml)
    {
        var fs = new StringReader(xml);
        var xs = new XmlSerializer(typeof(UserRegistry));
        var list = xs.Deserialize(fs) as UserRegistry;
        fs.Close();
        return list;
    }

    /// <summary>
    /// Save a user list to an xml string.
    /// </summary>
    public string SaveToXml()
    {
        var fs = new StringWriter();
        var xs = new XmlSerializer(typeof(UserRegistry));
        xs.Serialize(fs, this);
        fs.Close();
        return fs.ToString();
    }
}

/// <summary>
/// A user entry
/// </summary>
[Serializable()]
[XmlType(AnonymousType = true)]
public partial class LoginUser
{
    public static readonly LoginUser Empty = new LoginUser()
    {
        UserId=string.Empty,
        Salt  = string.Empty,
        PasswordHash = string.Empty
    };
    /// <summary>
    /// The list of users
    /// </summary>
    [XmlAttribute("id")]
    public string UserId
    {
        get;
        set;
    }

    /// <summary>
    /// The salted hash of the password
    /// </summary>
    [XmlAttribute("pwd")]
    public string PasswordHash
    {
        get;
        set;
    }
    /// <summary>
    /// The salt value used in the hash.
    /// </summary>
    [XmlAttribute("salt")]
    public string Salt
    {
        get;
        set;
    }
}

和一个示例对应的 XML 文件

// File: "UserList.xml"
<?xml version="1.0" encoding="utf-8" ?>
<Users>
  <User id="sue@email.com" pwd="Ei9p5Kiy8h7cy0nAxNimukxRhH4=" salt="OrAx1kBufa8=" />
  <User id="john@email.com" pwd="teeHjCrXzCxWosgZVTMWWeIvaso=" salt="hxQPkMK8t+0=" />
</Users>

请注意,上面的两个注册用户共享相同的密码,并且通过对其使用随机“盐”,密码哈希不同。 上面的实现不是最安全的,但它是将密码存储为文本的基本步骤。 我用来生成上面两个哈希的密码是字符串"12345678"

2. 登录表格

基本登录表单包含用户名和密码的文本框

登录

它还在启用OK按钮之前检查密码长度。 此按钮包含从 UI 构建LoginUser的代码。

该表单有两个属性,用于当前用户的LoginUser和用于注册用户列表的UserRegistry 当从 XML 文件加载表单时,将填充该列表。 当前用户最初是空的。 为方便起见,我使用注册用户列表在用户名文本框上启用自动完成功能。

public partial class LoginForm1 : Form
{
    public LoginUser User { get; set; }
    public UserRegistry UserRegistry { get; private set; }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        this.UserRegistry = UserRegistry.FromXml(File.ReadAllText("UserList.xml"));
        var usernames = UserRegistry.Users.Select((item) => item.UserId).ToArray();
        userNameTextBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
        userNameTextBox.AutoCompleteCustomSource.AddRange(usernames);
        this.User = LoginUser.Empty;
    }

    // other code omitted
}

代码的主要部分是检查密码和注册新用户。 我有两种方法,从OK按钮处理程序调用的IsUserValid()RegisterUser()

    public static bool IsUserValid(LoginUser user, string password)
    {
        var salt = Convert.FromBase64String(user.Salt);
        var pwd = Encoding.UTF7.GetBytes(password);
        var buffer = new byte[pwd.Length + salt.Length];
        Array.Copy(pwd, 0, buffer, 0, pwd.Length);
        Array.Copy(salt, 0, buffer, pwd.Length, salt.Length);
        var hash = sha1.ComputeHash(buffer);
        if (user.PasswordHash.Equals(Convert.ToBase64String(hash)))
        {
            return true;
        }
        return false;
    }

    public static LoginUser RegisterUser(string userName, string password)
    {
        var salt = new byte[8];
        rng.GetBytes(salt);
        var pwd = Encoding.UTF7.GetBytes(password);
        var buffer = new byte[pwd.Length + salt.Length];
        Array.Copy(pwd, 0, buffer, 0, pwd.Length);
        Array.Copy(salt, 0, buffer, pwd.Length, salt.Length);
        var hash = sha1.ComputeHash(buffer);
        return new LoginUser()
        {
            UserId = userName,
            Salt = Convert.ToBase64String(salt),
            PasswordHash = Convert.ToBase64String(hash)
        };
    }

    private void okButton_Click(object sender, EventArgs e)
    {
        this.User = UserRegistry[userNameTextBox.Text];
        if (this.User!=null)
        {
            if (IsUserValid(User, passwordTextBox.Text))
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            else
            {
                passwordTextBox.Clear();
                MessageBox.Show($"Incorrect password. Try Again.", "Login");
            }
        }
        else
        {
            if (MessageBox.Show($"User {userNameTextBox.Text} Not Found. Do you want to register?",
                "Login", MessageBoxButtons.YesNo)==DialogResult.Yes)
            {
                this.User = RegisterUser(userNameTextBox.Text, passwordTextBox.Text);
                this.UserRegistry.Add(User);
                MessageBox.Show($"User {userNameTextBox.Text} Registered.", "Login");
                this.DialogResult = DialogResult.OK;
                File.WriteAllText("UserList.xml", UserRegistry.SaveToXml());
                this.Close();
            }
        }            
    }

3. 验证

主窗体必须调用登录窗体,如果用户有效,它将返回一个有效的User属性条目,并从窗体.ShowDialog()方法返回DialogResult.OK

public partial class MDIParent1 : Form
{
    public MDIParent1()
    {
        InitializeComponent();
    }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        LoginForm1 login = new LoginForm1();
        login.StartPosition = FormStartPosition.CenterScreen;
        if (login.ShowDialog()==DialogResult.OK)
        {
            // Valid user
            userNameToolStripLabel.Text = login.User.UserId;
            return;
        }
        this.Close();
    }
}

在我的示例中,我使用主窗体右下角的用户身份。

米迪

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM