Сохранение текста в массивы C# форм - PullRequest
0 голосов
/ 26 марта 2020

Итак, я пытаюсь создать систему имени пользователя и пароля в формах C#, у меня есть вторая форма для создания вашей учетной записи, где вы можете ввести желаемое имя пользователя и соответствующий пароль. У меня есть 2 отдельных массива, один для имен пользователей, один для паролей, и я хочу, чтобы все, что пользователь вводит в текстовое поле для имени пользователя и пароля, содержалось в их соответствующих массивах, чтобы я мог связать их друг с другом. Как бы я go о сохранении того, что написано в текстовом поле, в массив?

Ответы [ 3 ]

1 голос
/ 26 марта 2020

Вместо массивов вы можете использовать C# - Hashtable

C# включает коллекцию Hashtable в пространстве имен System.Collections, которая аналогична обобщенной c коллекции словаря. Коллекция Hashtable хранит пары ключ-значение. Он оптимизирует поиск путем вычисления кода ha sh каждого ключа и сохраняет его внутри другого сегмента внутри, а затем сопоставляет код ha sh указанного ключа во время доступа к значениям. Вот пример, который демонстрирует вашу идею

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);    
}

Access Hashtable:

Вы можете получить значение существующего ключа из Hashtable, используя индексатор. Обратите внимание, что для индексатора хеш-таблицы требуется ключ.

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 
0 голосов
/ 28 марта 2020

В C# массивы лучше всего использовать, когда число элементов известно и фиксировано. В противном случае для добавления / удаления элементов будет достаточно общего List<T>.

Я думаю, что вы спрашиваете, как разработать модель данных для зарегистрированных пользователей и как взаимодействовать с этой моделью с помощью пользовательского интерфейса.

Эта головоломка состоит из нескольких частей:

1. Модель данных

Начните с класса для хранения информации о пользователе (LoginUser ниже) и класса для хранения списка авторизованных пользователей (UserRegistry ниже).

data

Добавьте методы для загрузки / сохранения реестра пользователей в Xml или любом другом хранилище, которое вы пожелаете. В моем примере ниже я использую встроенный XmlSerializer для go от данных к файлу и обратно.

Полный код в моем примере

/// <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

// 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>

Обратите внимание, что оба зарегистрированных пользователя выше используют один и тот же пароль, и, используя случайную "соль", пароль ha sh отличается. Вышеприведенная реализация не является наиболее безопасной, но это базовый шаг выше, чем хранение паролей в виде текста. Пароль, который я использовал для генерации обоих хешей выше, это строка "12345678".

2. Форма входа

Форма входа basi c содержит текстовые поля для имени пользователя и пароля

login

, она также проверяет длину пароля перед включением кнопки OK . Эта кнопка содержит код, который создает 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
}

Основная часть кода - проверка пароля и регистрация нового пользователя. У меня есть два метода, IsUserValid() и RegisterUser(), которые вызываются из обработчика кнопки OK .

    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 и вернет DialogResult.OK из метода .ShowDialog() формы.

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();
    }
}

В моем примере я использую личность пользователя в правом нижнем углу основной формы.

mdi

0 голосов
/ 27 марта 2020

Если вы хотите использовать два массива для сохранения имени пользователя и пароля, вы можете использовать индекс для их соединения.

string[] users = new string[10];
string[] password = new string[10];
int id = 0;

private void btSignUp_Click(object sender, EventArgs e)
{
    if (id > users.Length - 1)
    {
        MessageBox.Show("the array is full");
        return;
    }
    users[id] = tbUser.Text;
    password[id] = tbPWD.Text;
    id++;
}

private void btCheckPWD_Click(object sender, EventArgs e)
{
    if (Array.IndexOf(users, tbUser.Text) != -1)
        MessageBox.Show($"the pwd of {tbUser.Text} is {password[Array.IndexOf(users, tbUser.Text)]}");
    else
        MessageBox.Show("no such user");
}

Но длина массива фиксирована, вам нужно указать длину при объявлении Это. Поэтому я думаю, Список - лучший выбор.

И при работе с парами ключ-значение я рекомендую использовать Словарь для их хранения.

Dictionary<string, string> user_pwd = new Dictionary<string, string>();

private void btSignUp_Click(object sender, EventArgs e)
{
    user_pwd.Add(tbUser.Text, tbPWD.Text);
}

private void btCheckPWD_Click(object sender, EventArgs e)
{
    if(user_pwd.ContainsKey(tbUser.Text))
        MessageBox.Show($"the pwd of {tbUser.Text} is {user_pwd[tbUser.Text]}");
    else
        MessageBox.Show("no such user");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...