Есть ли способ, которым я могу очистить свой код, назначив запрос linq одной переменной типа string? - PullRequest
0 голосов
/ 14 апреля 2020

Я создал систему входа в систему для проекта, над которым я работал, и пока он работает, похоже, это не самый эффективный способ сделать это. Это проект WPF / C#, связанный с базой данных SQLite, которая использует LINQ для запросов. В идеале я хотел бы, чтобы запрос выдавал одну переменную типа string, чтобы я мог манипулировать ею и сравнивать ее с тем, что вводит пользователь.

List<Engineer> engineers;
private void LoginButton_Click(object sender, RoutedEventArgs e)
        {
            string username = UsernameField.Text;
            string password = PasswordField.Password.ToString();
            string hashedPasswordString = "";
            string saltString = "";

            //establishes connection
            using (SQLiteConnection conn = new SQLiteConnection(App.engineerDatabasePath))
            {

                engineers = conn.Table<Engineer>().ToList();
                //Queries for a list containing the respective hashed passwords. This will only contain one password since the emails are unique
                var hashedpasswordlist = from c in engineers
                                     where c.Email == username
                                     select c.Password;

                //Take the password in the list and assign it to a string variable that can be compared
                foreach (var item in hashedpasswordlist)
                {
                    hashedPasswordString = item;
                }

                //Queries for a list containing the respective salts. This will only contain one salt since the emails are unique
                var saltlist = from c in engineers
                               where c.Email == username
                               select c.Salt;

                //Take the salt in the list and assign it to a variable to the password input, creating a hash value that is to be assigned
                foreach (var item in saltlist)
                {
                    saltString = item;
                }

                //Confirmation that the implementation works as it should
                if (GenerateSHA256Hash(password, saltString) == hashedPasswordString) 
                {
                    MessageBoxResult deleteConfirmation = MessageBox.Show("IT WORKS!", "Grats", MessageBoxButton.YesNo, MessageBoxImage.Warning);
                }

            }
            //Allows you to log in regardless of whether your login details are correct. This is the case for testing purposes.
            MainWindow MainWindow = new MainWindow();
            MainWindow.Show();
            this.Close();
        }

Вот GenerateSHA256Ha sh метод и метод ByteArrayToHexString

 public string GenerateSHA256Hash(string input, string salt)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(input + salt);
            System.Security.Cryptography.SHA256Managed sha256hashtring = new System.Security.Cryptography.SHA256Managed();
            byte[] hash = sha256hashtring.ComputeHash(bytes);

            return ByteArrayToHexString(hash);
        }

        public static string ByteArrayToHexString(byte[] ba)
        {
            StringBuilder hex = new StringBuilder(ba.Length * 2);

            foreach (byte b in ba)
            {
                hex.AppendFormat("{0:x2}", b);
            }

            return hex.ToString();
        }

Ответы [ 4 ]

2 голосов
/ 14 апреля 2020

Если вы хотите получить фактический пароль и сравнить его с тем, что ввел пользователь, вам не следует этого делать. По соображениям безопасности пароль не должен храниться в извлекаемом формате в базе данных, поэтому хеширование введенного пароля и сравнение его с ha sh в базе данных намного более безопасно (и не намного менее эффективно), чем прямое сравнение.

Тем не менее, вы могли бы получить и соль, и га sh за один шаг и использовать SingleOrDefault(), поскольку вы ожидаете только один элемент:

//Queries for a list containing the respective hashed passwords. This will only contain one password since the emails are unique
var saltedPassword = (from c in conn.Table<Engineer>()
                     where c.Email == username
                     select new {c.Password, c.Salt}).SingleOrDefault();

//TODO: Add handling for when password is not found (saltedPassword is null)

hashedPasswordString = saltedPassword.Password;
saltString = saltedPassword.Salt;
1 голос
/ 14 апреля 2020

Вы запрашиваете таблицу Engineer, поэтому очевидно, что возвращаемый результат будет Engineer объектом, и, поскольку вы запрашиваете тот же объект, вам нужно запросить таблицу, получить результаты как Engineer объект, а затем перемещаться по его свойствам.

Нет необходимости запрашивать несколько раз, достаточно одного раза.

private void LoginButton_Click(object sender, RoutedEventArgs e)
{
    // Basic null handling 
    if(string.IsNullOrEmpty(UsernameField.Text)) { throw new ArgumentNullException(nameof(UsernameField.Text)); }

    if(string.IsNullOrEmpty(PasswordField.Password?.ToString())) { throw new ArgumentNullException(nameof(UsernameField.Text)); }

    //establishes connection
    using (SQLiteConnection conn = new SQLiteConnection(App.engineerDatabasePath))
    {
        // get the Engineer object
        var engineer = conn.Table<Engineer>().FirstOrDefault(c => c.Email.Equals(UsernameField.Text, StringComparison.OrdinalIgnoreCase));

        // generate the password
        var password = GenerateSHA256Hash(PasswordField.Password.ToString(), engineer.Salt); 

        //Confirmation that the implementation works as it should
        if (engineer.Password.Equals(password))
        {
            MessageBoxResult deleteConfirmation = MessageBox.Show("IT WORKS!", "Grats", MessageBoxButton.YesNo, MessageBoxImage.Warning);
        }

    }
    //Allows you to log in regardless of whether your login details are correct. This is the case for testing purposes.
    MainWindow MainWindow = new MainWindow();
    MainWindow.Show();
    this.Close();
}
0 голосов
/ 15 апреля 2020

Итак, я взял метод @D Stanley и скомбинировал его с отсутствием переменных @ iSR5, чтобы создать следующее:

using (SQLiteConnection conn = new SQLiteConnection(App.engineerDatabasePath))
                {

                    var saltedPassword = (from c in conn.Table<Engineer>()
                                          where c.Email == UsernameField.Text
                                          select new { c.Password, c.Salt }).SingleOrDefault();

                    if (saltedPassword != null)
                    {
                        if (GenerateSHA256Hash(PasswordField.Password.ToString(), saltedPassword.Salt) == saltedPassword.Password)
                        {
                            MessageBox.Show("Correct credentials, click ok to continue", "Access Granted", MessageBoxButton.OK);
                            MainWindow MainWindow = new MainWindow();
                            MainWindow.Show();
                            this.Close();
                        }
                    }
                    else
                    {
                        MessageBox.Show("Incorrect credentials", "Error", MessageBoxButton.OK, MessageBoxImage.Information);
                    }

                }

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

Спасибо, ребята:)

0 голосов
/ 14 апреля 2020

Вы можете использовать свою первую строку и строить на ней

engineers = conn.Table<Engineer>().ToList();



var engineer = conn.Table<Engineer>().First(x=>x.Email.Equals(username)); 

var password = conn.Table<Engineer>().First(x=>x.Email.Equals(username)).Password;

var saltString = engineer.Salt

var pw = engineer.Password
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...