I have in the DB Sid and password and it contain the Sid=senan and the password=pass1234
when I enter this details into my login screen always I get fail messagebox
SqlDataAdapter cmd = new SqlDataAdapter("select Count(*) from [user] where Sid=' " + textBox1.Text + " ' and password='" + textBox2.Text + "'", cnn);
DataTable dt = new DataTable();
cmd.Fill(dt);
if (dt.Rows[0][0].ToString() == "1")
MessageBox.Show("pass");
else
MessageBox.Show("fail");
The error arises from a simple typo. You have spaces added to the value passed for the Sid condition.
However your query should be rewritten in this way
string cmdText = "select Count(*) from [user] where Sid=#sid and password=#pwd";
SqlCommand cmd = new SqlCommand(cmdText, cnn)
cmd.Parameters.AddWithValue("#sid", textBox1.Text);
cmd.Parameters.AddWithValue("#pwd", textBox2.Text);
int count = Convert.ToInt32(cmd.ExecuteScalar());
if (count > 0)
MessageBox.Show("pass");
else
MessageBox.Show("fail");
This approach uses a parameterized query to avoid Sql Injection, and uses directly an SqlCommand without building the SqlDataAdapter and a DataTable. The SqlCommand.ExecuteScalar is the correct method to use when you need to retrieve simply the first column of a single row or call a scalar T-SQL function like COUNT()
As a side note, keep in mind that storing passwords in clear text in your database is a big security concern. Whoever has access to the database will be able to read the passwords of every user. The passwords should be stored as a computed hash and checked repeating the hashing algorithm on the user entered data.
Related
This is the student info table where the student info comes from //This is the login code for the user and it get the user log in info from the studentinfo table.
private void btnlogin_Click(object sender, EventArgs e)
{
i = 0;
con.Open();
MySqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select * from stdinfotable WHERE Username='" + textuser.Text + "' and Password= '" + textpass.Text + "'";
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
MySqlDataAdapter dta = new MySqlDataAdapter(cmd);
dta.Fill(dt);
i = Convert.ToInt32(dt.Rows.Count.ToString());
if(i==0)
{
MessageBox.Show("Error");
}
else
{
this.Hide();
StudentPage f = new StudentPage();
f.Show();
MySqlDataAdapter data = new MySqlDataAdapter("ViewAllGrades", con);
data.SelectCommand.CommandType = CommandType.StoredProcedure;
DataTable dtTable = new DataTable();
data.Fill(dtTable);
dtTable.Select("Last_Name");
f.stdGrade.DataSource = dtTable;
f.stdGrade.Columns[0].Visible = false;
}
con.Close();
}
This is the ViewlAllGrades stored procedure where the grade info is returned from
CREATE DEFINER=`root`#`localhost` PROCEDURE `ViewAllGrades`()
BEGIN
SELECT *
FROM Grades;
END
I am trying to make it so only the logged in user can view his own grade rather than viewing every user grade. So I am wondering should I try to do within the stored procedure or in Visual Studio and how would I achieve such thing? Also my primary keys which are ID are from both table are auto incremented so I cant not necessarily use those
Right now your stored procedure is selecting all of the grades. First thing to do would be to parameterize the query, accepting the user as the input, and using the WHERE clause to find only the grades for that student. Without seeing your tables, I cannot tell you exactly what this would look like, but as an example: SELECT * FROM Grades WHERE StudentId = #StudentId;
The second thing you need to figure out is how to get the current user's student id and then pass it to the stored procedure. Again, without seeing your tables, I can hardly guess. It appears you already have the username of the current user. Are you able to run a query to find the studentId from the username? If so, then you first need to run that procedure with username as the parameter to get the studentId.
A third concern is with your first query. Since it has not been parameterized, it is susceptible to SQL injection attacks. This poses a MAJOR security risk. If someone maliciously enters a username or password, they can escape the SQL you intended to run and drop all of your tables.
Hopefully that helps!
After I try to output the password in the dataGrid, from the given Username in the txt_Username textbox, I get this error message:
MySql.Data.MySqlClient.MySqlException: "Unknown column 'Test' in 'where clause'"
MySqlDataAdapter da = new MySqlDataAdapter("Select Password from tbl_anmeldedaten Where Username=" + txt_Username.Text, con);
da.SelectCommand.CommandType = CommandType.Text;
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
The exact cause of the error is that you are trying to execute the following query:
SELECT Password
FROM tbl_anmeldedaten
WHERE Username = Test;
Does it look like Test should have single quotes around it? Yes, it should, and you could add that to your raw query. But, concatenating a query like this in C# leaves open the possibility for SQL injection. A much better approach is to use prepared statements:
string sql = "SELECT Password FROM tbl_anmeldedaten WHERE Username = #val1";
MySqlCommand cmd = new MySqlCommand(sql, MySqlConn.conn);
cmd.Parameters.AddWithValue("#val1", txt_Username.Text);
cmd.Prepare();
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
// consume a record in the result set
}
You are using string concatenation which is a vector for SQL injection attacks. Perhaps the username in the text field is doing some SQL which it shouldn't be allowed to (for instance '' OR Test=1. There are plenty of resources on using parameterized queries which should remedy the problem.
private void buttonLogin_Click(object sender, EventArgs e)
{
SqlConnection sqlcon = new SqlConnection(#"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\sesha\Documents\Visual Studio 2013\Projects\Achievers - Grocery Management System\Login Database\Login DB.mdf;Integrated Security=True;Connect Timeout=30");
string query = "Select * from [Table] where username = '" + textBoxUsername.Text.Trim() + "' and password = '" + textBoxPassword.Text.Trim() + "'";
SqlDataAdapter sda = new SqlDataAdapter(query, sqlcon);
DataTable dt = new DataTable();
sda.Fill(dt);
if (dt.Rows.ToString() == "1")
{
Dashboard objDashboard = new Dashboard();
this.Hide();
objDashboard.Show();
}
else
{
MessageBox.Show("Check your username and password");
}
}
If you have no control on how your database is created
Query your database with just the username
Fill a datatable with your fields
Use the values in ur datatable for comparison using String.compare
(remember to hash your password before saving and hash your input for comparision)
In the case of your posted code, instead of just relying on the comparison in the SQL WHERE clause to do the check for you, if a matching row is found then you could re-check the entered value using a case-sensitive comparison against the value of the password column of your DataTable (dt).
If the password was stored in the database in a hashed format, the hashing algorithm would take care of the case sensitivity as any difference in the case of the value entered would result in a different hash value. As many comments have stated, when storing passwords, the password should never be stored in plain text. As a bare minimum the password should be hashed, preferably it should also be salted before being hashed.
Finally, you could look at changing the database collation, if you have access to make changes to the database itself. By default, SQL Server uses a collation which is not case sensitive. For more information, read https://learn.microsoft.com/en-us/sql/t-sql/statements/collations (as commented by Tim on your question).
Hi and thank you in advance for any help.
I have a problem with reading from a SQL database.
The command works 100% if i specify the column name
SqlCommand com = new SqlCommand("Select * From Stock where Fuad > 0 ", con);
but the problem is that my program tracks stock movement, between users, and i need to use a command similar to
String currentuser = //(current user logged in, passed when logged in)
SqlCommand com = new SqlCommand("Select * From Stock where '" + currentuser + "' > 0 ", con);
but when i run this code i get an error: "Conversion failed when converting varchar value 'Fuad' to datatype int." Now i know my column in sql is set to Int. but how does that affect the column name?
i can go and write this out for every user, but that would be pointless in the long run as for every new staff member i will have to write a update. is there a way to use a generic caller ie: currentuser to help with this.
the SQL database is setup with int columns, each column has the technicians/staff members name, and tracks how many of each part he currently has booked out.
i just cant figure out how to call the column name if its an Int, because any string that i use will be varchar.
the full code for loading this is
SqlConnection con = new SqlConnection(Connectstring)
con.Open();
SqlCommand com = new SqlCommand("Select * From Stock where '" + currentuser + "' > 0 ", con);
try
{
SqlDataReader dr = com.ExecuteReader();
while (dr.Read())
{
ListViewItem item = new ListViewItem(dr["ItemName"].ToString());
item.SubItems.Add(dr["ItemCode"].ToString());
item.SubItems.Add(dr[currentuser].ToString());
listView1.Items.Add(item);
}
dr.Close();
and as said earlier this works 100% if i replace the "currentuser" with the column name. is it possible to call it with a string, if not i will have to find another way to do this.
Try using [Fieldname] this way:
String currentuser = //(current user logged in, passed when logged in)
SqlCommand com = new SqlCommand("Select * From Stock where [" + currentuser + "] > 0 ", con);
String currentuser = //(current user logged in, passed when logged in)
SqlCommand com = new SqlCommand("Select * From Stock where " + currentuser + " > 0 ", con);
Just don't use that single brackets for column name "'".
This is my password textbox aspx elements:
<label for="password">Password</label>
<asp:Text Box ID="User Password" runat ="server" Text Mode ="Password" ></asp:Text Box>
This is my code behind
protected void LoginSubmit_Click(object sender, EventArgs e)
{
BOL ObjectBOL = new BOL();
BAL ObjectBAL = new BAL();
ObjectBOL.UserName_value = UserText.Text;
ObjectBOL.UserPassword_value = UserPassword.Text;
try
{
String Login = ObjectBAL.LoginBAL(ObjectBOL);
int i = int.Parse(Login);
if (i > 0)
{
Response.Redirect("dashboard.aspx", false);
}
else
{
//UserText.Text = "";
//UserPassword.Text = "";
lblMsg.Text = (" Login Failed.... Try Again...");
}
}
catch (Exception LoginException)
{
throw LoginException;
}
finally
{
ObjectBAL = null;
}
}
When the user enters the password in upper case or lower case letters it was accepting the value and redirecting to the next page.
SqlCommand cmd = new SqlCommand ("select count (*) from UserTable where User_Name='" + Login.UserName_value +
"'and User_Password='" + Login.UserPassword_value + "'", con);
string str = cmd.ExecuteScalar().ToString();
return str;
There are two solution for this problem
Change your database table nature .By default SQL server do the case insensitive comparison you need to alter your db table.
ALTER TABLE UserTable
ALTER COLUMN User_Password VARCHAR(20)
COLLATE Latin1_General_CS_AS
Or you can append COLLATE Latin1_General_CS_AS to every query at last without altering your table.
Latin1_General_CS_AS is for case sensitive and Latin1_General_CI_AS for case insensitive comparison
how to make case sensitive comparison in SQL Server
Or you can convert your password in binary then store in db and compare binary content from db and user entered password.
Suggestion
You can go with first solution it will take less time. but second solution is more secure then first one. Do read about this on google. you will find the cons of the directly storing password in plain text.
As mentioned in comment your code is vulnerable to SQL Injection attack. Use parametrize query instead.
Update your SQL Command query with COLLATE Latin1_General_CS_AS as mentioned below to compare string with case sensitive:
SqlCommand cmd = new SqlCommand ("select count (*) from UserTable where User_Name='" + Login.UserName_value +
"' and User_Password='" + Login.UserPassword_value + "' COLLATE Latin1_General_CS_AS", con);
string str = cmd.ExecuteScalar().ToString();
return str;
So I see a couple issues here that you should really look at, let me address those then I'll help with the question you asked.
First, as mentioned in the comments by #Erik Philips, you should be using parameterized queries rather than string concatenation.
Second, you really should be hashing your passwords using a strong hashing algorithm, so if/when your DB gets compromised, you don't divulge all your user's passwords to the attacker.
Ok, as for the actual question at hand you have two options. The far more common solution I've seen is to do the Select just based on the user name, then compare the hashed passwords in C# code to determine whether the user should be logged in or not.
The other option would be to use a case sensitive query in SQL, which in SQL Server requires you to assign a collation via the COLLATE command (either to the query or to the column), perhaps assigning it to whichever relevant character set you want: http://msdn.microsoft.com/en-us/library/ms144250(v=sql.105).aspx
You need to change your sql query only. no need to change table nature and anything else.
SqlCommand cmd = new SqlCommand ("select count(*) from UserTable where User_Name COLLATE Latin1_general_CS_AS ='" + Login.UserName_value + "'and User_Password COLLATE Latin1_general_CS_AS ='" + Login.UserPassword_value + "'", con);
con.Open();
string str = cmd.ExecuteScalar().ToString();
con.Close();
return str;
SqlCommand cmd = new SqlCommand ("select COUNT(*) from UserTable where (CAST(User_Name as varbinary(50))=cast('"+ Login.UserName_value+"' as varbinary)) and (CAST(User_Password as varbinary(50))=cast('"+Login.UserPassword_value+"' as varbinary)),con);
con.Open();
string str = cmd.ExecuteScalar().ToString();
con.Close();
return str;
try this this will work
Please refer the below link, I think as mentioned above collate is the way to go about.
http://www.mytecbits.com/microsoft/sql-server/case-sensitive-search-fetching-lowercase-or-uppercase-string