Click here to Skip to main content
14,735,733 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm currently building a C# application that I would like to have a basic login form before it opens the main form.

In SQL I have a basic users table with columns; username, password.
I'm using hashing to not make the password visable in SQL to be secure.
I've followed the instructions at the top of this article. Storing passwords in a secure way in a SQL Server database[^]

The problem is now the passwords are hashed I can't run my login query in my application.
What do I need to add to allow it to read a password hash?

This is what I'm currently doing;
It works fine when the password is displayed in SQL as basic VARCHAR text characters.

<pre lang="c++">

            SqlConnection sqlconn = new SqlConnection(@"Server= localhost; Database= DatabaseName; Integrated Security=True;");
            String query = "Select * from Users where LoginName = '" + userlogin.Text.Trim() + "'and PasswordHash = '" + passwordbox.Text.Trim() + "'";
            SqlDataAdapter sda = new SqlDataAdapter(query, sqlconn);
            DataTable dtbl = new DataTable();
            sda.Fill(dtbl);
            if (dtbl.Rows.Count == 1)

            {


                this.Hide();
                Form1 form1 = new Form1();
                form1.Show();


What I have tried:

I've tried looking for articles on this but none that seem very straight forward?
Posted
Updated 28-Apr-20 5:03am

You did not fully follow the article you are referencing, since you did not write any stored procedure to perform login operation.
Since the salting/hashing happens on the server, you do not have the choice but to create this stored procedure to perform the salting/hashing on the server side.
   
Comments
Maciej Los 28-Apr-20 9:27am
   
5ed!
phil.o 28-Apr-20 9:32am
   
Thanks :)
Don't do it like that! Never concatenate strings to build a SQL command. It leaves you wide open to accidental or deliberate SQL Injection attack which can destroy your entire database. Always use Parameterized queries instead.

When you concatenate strings, you cause problems because SQL receives commands like:
SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
The quote the user added terminates the string as far as SQL is concerned and you get problems. But it could be worse. If I come along and type this instead: "x';DROP TABLE MyTable;--" Then SQL receives a very different command:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Which SQL sees as three separate commands:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
A perfectly valid SELECT
DROP TABLE MyTable;
A perfectly valid "delete the table" command
--'
And everything else is a comment.
So it does: selects any matching rows, deletes the table from the DB, and ignores anything else.

So ALWAYS use parameterized queries! Or be prepared to restore your DB from backup frequently. You do take backups regularly, don't you?

ANd on a login form?
All I have to do is try in teh usrename box:
x' --
And SQL will log me in as any user I like without a password ...

Don't return all columns: You already know what the username is and you ignore everything else.

Checking the hash is easy. There is some information on how to do it here: Password Storage: How to do it.[^]
   
So once you get those procedures all into place, you will be using code something like this to validate.
SqlConnection sqlconn = new SqlConnection(@"Server= localhost; Database= DatabaseName; Integrated Security=True;");

SqlCommand cmd = new SqlCommand("uspLogin", sqlconn);
cmd.CommandType = CommandType.StoredProcedure;

SqlParameter spResp = New SqlParameter("@responseMessage", SqlDbType.NVarChar, 32);
spResponse.Direction = ParameterDirection.Output;

cmd.Parameters.AddWithValue("@pLoginName", userlogin.Text.Trim());
cmd.Parameters.AddWithValue("@pPassword", passwordbox.Text.Trim());
cmd.Parameters.Add(spResp);

sqlConn.Open();
cmd.ExecuteNonQuery();
string LoginStatus = (string)spResp.value;
cmd.Dispose();
sqlconn.Close();
sqlconn.Dispose();

if (LoginStatus != "User successfully logged in") {
	// Login Failed
} else {
	// continue into application
}
Please note that I am only checking if the login was successful, and not checking why they failed (username or password).
The security standards that I use dictate that we don't tell people why they failed. as that tells too much information; mainly if an account exists or not

SqlParameter reference:
SqlParameter Class (System.Data.SqlClient) | Microsoft Docs[^]
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900