-4

I am trying to learn C# and I'm writing a system where you have to log in, I'm storing the data in a database and loading in with code. The data is loaded in with no errors and I can Console.WriteLine it and it's all fine, but when I run comparison on it it always fails. Here is the relevant code.

Edit: I have tried without using the $ in the string comparison and it still doesn't work

    private void login_button_Click(object sender, EventArgs e)
    {
        // App.config stores configuration data
        // System.Data.SqlClient provides classes
        // for accessing a SQL Server DB

        // connectionString defines the DB name, and
        // other parameters for connecting to the DB

        // Configurationmanager provides access to
        // config data in App.config
        string provider = ConfigurationManager.AppSettings["provider"];

        string connectionString = ConfigurationManager.AppSettings["connectionString"];

        // DbProviderFactories generates an 
        // instance of a DbProviderFactory
        DbProviderFactory factory = DbProviderFactories.GetFactory(provider);

        // The DBConnection represents the DB connection
        using (DbConnection connection =
            factory.CreateConnection())
        {
            // Check if a connection was made
            if (connection == null)
            {
                Console.WriteLine("Connection Error");
                Console.ReadLine();
                return;
            }

            // The DB data needed to open the correct DB
            connection.ConnectionString = connectionString;

            // Open the DB connection
            connection.Open();

            // Allows you to pass queries to the DB
            DbCommand command = factory.CreateCommand();

            if (command == null)
            {
                return;
            }

            // Set the DB connection for commands
            command.Connection = connection;

            // The query you want to issue
            command.CommandText = $"SELECT * FROM Users WHERE Username = '{username_input.Text}'";

            // DbDataReader reads the row results
            // from the query
            using (DbDataReader dataReader = command.ExecuteReader())
            {
                dataReader.Read();
                //while(dataReader.Read())
                //{
                    if ($"{password_input.Text}" ==$"{dataReader["Password"]}")
                    {
                        MessageBox.Show("Logged in");
                    }
                    else
                    {
                        MessageBox.Show("Invalid Credentials!");
                    }
                //}
            }
        }
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Throupy
  • 21
  • 6
  • Your script is at risk for SQL Injection Attacks. – gunr2171 Nov 29 '18 at 17:50
  • @gunr2171 that is not the point, I am learning C# and how to interact with databases not how to secure applications. – Throupy Nov 29 '18 at 17:51
  • did you look with your debugger to see what is in username_input.Text and dataReader["Password"] – pm100 Nov 29 '18 at 17:51
  • 3
    @Throupy it might not be the point of your question, but it is nonetheless solid advice to follow. Develop good habits, not bad ones. Right now, you are developing a bad habit of writing non-parametrized queries. Learn to do it the right way the first time. –  Nov 29 '18 at 17:52
  • 5
    `I am learning C# and how to interact with databases` <= then you should parameterize your queries. It is a minimal amount of effort to do so. – Igor Nov 29 '18 at 17:52
  • While we can't see your actual data model, it appears you are comparing a `username` textbox value with a `password` value coming out of the DB... – Steve Danner Nov 29 '18 at 17:52
  • 1
    and why not just plain old `if(username_input.TExt == dataReader["Password")`? Why the complicated string interpolate – pm100 Nov 29 '18 at 17:52
  • @SteveDanner It's supposed to be password_input, sorry I have ammended it now. – Throupy Nov 29 '18 at 17:53
  • @Igor It's supposed to be password_input, i've changed it. And they are the exact same when I look in the debugger – Throupy Nov 29 '18 at 17:54
  • @pm100 I did it too see if it would make a difference, it did not work with OR without them – Throupy Nov 29 '18 at 17:54
  • Perhaps try using `Trim()` on both strings when comparing. That's burned me before – Steve Danner Nov 29 '18 at 17:55
  • Why are you doing `$"{password_input.Text}"`? That is unnecessary. `password_input.Text` will already be a string, no need to use string interpolation. – mason Nov 29 '18 at 17:55
  • @gunr2171 thank you for telling me though, I will look into it. – Throupy Nov 29 '18 at 17:55
  • @mason yes I have tried, no luck :( – Throupy Nov 29 '18 at 17:56
  • DID YOU STOP ON THE COMPARE LINE WITH A DEBUGGER AND LOOK AT THE VALUES YOU ARE COMPARING - you problem will be immediately obvious - sorry to shout but I needed to get yr attention – pm100 Nov 29 '18 at 17:56
  • @Throupy What do you mean "no luck"? There is no luck needed. I'm not telling you how to fix your problem, I'm telling you how to clean up your syntax. – mason Nov 29 '18 at 17:57
  • @Throupy, regarding the `Trim` suggestion, if your Password field is a CHAR in the database rather than a VARCHAR, that WILL be the issue. – Steve Danner Nov 29 '18 at 17:58
  • @pm100 they are the exact same when I look in the debugger. If i'm doing it correct that is. – Throupy Nov 29 '18 at 17:58
  • @SteveDanner yes, It in an nchar in the database, I will change it to varchar now – Throupy Nov 29 '18 at 17:59
  • @Throupy They can't be the exact same. If they were, you wouldn't be here asking this question. Are you positively sure neither begins or ends with whitespace, and that neither contains non-printing unicode characters? –  Nov 29 '18 at 18:00
  • 4
    This entire code is misguided; [that is not how to implement passwords](http://plaintextoffenders.com/faq/devs). – Dour High Arch Nov 29 '18 at 18:04
  • they are not the same clearly. The most likely issues (as others have said) is that you have trailing whitespace on one of the values, hence the suggestion you do Trim on them – pm100 Nov 29 '18 at 18:42
  • Possible duplicate of [What are good ways to prevent SQL injection?](https://stackoverflow.com/questions/14376473/what-are-good-ways-to-prevent-sql-injection) – mjwills Nov 29 '18 at 20:42

2 Answers2

3
  1. Always use parameters instead of string concatenation in your queries. It guards against sql injection (not applicable to MS Access) and ensures you never has issues with strings that contain escape charaters.
  2. I notice you probably have password as plain text, never store passwords in plain text!
  3. In this particular case using ExecuteScalar simplifies the logic (IMO). If you were to want to return data and read it using a data reader then do not use * for your return. Specify your column names instead. This will guard your code against schema changes like columns being added or column order changes.
command.CommandText = "SELECT [Password] FROM [Users] WHERE [Username] = @userName";

// using DbCommand adds a lot more code than if you were to reference a non abstract implementation when adding parameters
var param = command.CreateParameter();
param.ParameterName = "@userName";
param.Value = username_input.Text;
param.DbType = DbType.String;
param.Size = 100;
command.Parameters.Add(param);

// compared with SqlDbCommand which would be 1 line
// command.Parameters.Add("@userName", SqlDbType.VarChar, 100).Value = username_input.Text;

var result = command.ExecuteScalar()?.ToString();
if(string.Equals(password_input.Text, result, StringComparison.Ordinal))
    MessageBox.Show("Logged in");
else
    MessageBox.Show("Invalid Credentials!");
Igor
  • 60,821
  • 10
  • 100
  • 175
0

Start off on the right foot with learning C# with some advice Ive seen in the comments already as well some additional advice below:

Parameterize your queries at the very minimum The below way is Open to SQL injection

 command.CommandText = $"SELECT * FROM Users WHERE Username = '{username_input.Text}'";

This instead should be written as: (Keep in mind there are shorter ways to write this but I'm being explicit since you are learning)

var usernameParam = new SqlParameter("username", SqlDbType.VarChar);
usernameParam.Value = username_input.Text;

command.Parameters.Add(usernameParam);
command.CommandText = "SELECT * FROM Users WHERE Username = @username";

Secondly, debugging is your friend. You need to add a breakpoint on the line that is failing and utilize the built in Visual Studio Watchers to look at your variables. This will tell you more information than a console.writeline() and solve more problems than you might imagine.

Scornwell
  • 597
  • 4
  • 19
  • Thank you very much for your time, as far as the visual studio debugging goes? How do I do that, I very never really used vs before – Throupy Nov 29 '18 at 18:05
  • 1
    @Throupy That's not really something you should just ask people about. You should instead research it. Microsoft has plenty of documentation out there for it, and there's lots of videos on YouTube and Channel 9 showing the usage of Visual Studio's debugger. – mason Nov 29 '18 at 18:07
  • Is that the IDE you are using? As a new programmer, you need to conduct some research, a Simple Google Search of 'Debugging In visual Studio' leads to an amazing resource here https://learn.microsoft.com/en-us/visualstudio/debugger/debugger-feature-tour?view=vs-2017 – Scornwell Nov 29 '18 at 18:08