This question already has answers here:
SQL Server Invalid column name when adding string value
(5 answers)
Closed 6 years ago.
Error is showing that invalid column name mustufain.
mustufain is the value of UserName.Text.toString()
string query = "select userid from register where username = " + UserName.Text.ToString() + " and " + "password = " + Password.Text.ToString();
SqlCommand cmd1 = new SqlCommand(query,connection);
connection.Open();
SqlDataReader rd1 = cmd1.ExecuteReader();
while(rd1.Read())
{
Session["checkuserid"] = rd1["userid"];
}
connection.Close();
Firstly, you should not be using string concatenation to build your queries as it can leave you vulnerable to things like SQL Injection attacks and it can cause issues with your queries being incorrect (as you are missing tick marks around your parameters) :
// This would attempt to state username = mustufain instead of
// username = 'mustufain' (and SQL doesn't know what mustufain is)
var query = "select userid from register where username = '" + UserName.Text + "' and " + "password = '" + Password.Text + "'";
A better approach using parameterization would look like the following, which avoids the incorrect syntax and offers you protection against any nasty injections :
// Open your connection
using(var connection = new SqlConnection("{your connection string}"))
{
// Build your query
var query = "SELECT TOP 1 userid FROM register WHERE username = #username AND password = #password";
// Build a command (to execute your query)
using(var command = new SqlCommand(query, connection))
{
// Open your connection
connection.Open();
// Add your parameters
command.Parameters.AddWithValue("#username",UserName.Text);
command.Parameters.AddWithValue("#password",Password.Text);
// Execute your query
var user = Convert.ToString(command.ExecuteScalar());
// If a user was found, then set it
if(!String.IsNullOrEmpty(user))
{
Session["checkuserid"] = user;
}
else
{
// No user was found, consider alerting the user
}
}
}
Finally, you may want to reconsider how you are storing your credentials (in clear text). ASP.NET offers a wide variety of providers that can help handle this process for you so that you don't have to do it yourself.
You are trying to concatenate strings to build an sql query and, as usual, you get errors. In your specific case you forget to enclose your string values between single quotes. But the only correct way to do this query is by the way of a parameterized query
string query = #"select userid from register
where username = #name and password = #pwd";
using(SqlCommand cmd1 = new SqlCommand(query,connection))
{
connection.Open();
cmd1.Parameters.Add("#name", SqlDbType.NVarChar).Value = UserName.Text;
cmd1.Parameters.Add("#pwd", SqlDbType.NVarChar).Value = Password.Text;
using(SqlDataReader rd1 = cmd1.ExecuteReader())
{
....
}
}
Notice also that storing passwords in clear text in your database is a very bad practice and a strong security risk. On this site there are numerous questions and answers that explain how to create an hash of your password and store that hash instead of the clear text
For example: Best way to store passwords in a database
Related
I am creating a simple app where users create accounts. I want for the user to be able to change their password after making the account.
I am making this in C# using Oledb.
string test = "testing";
con.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = con;
string query = "UPDATE tbl_users SET password = '" + test + "' WHERE username = '" + txtLoginUsername.Text + "'";
MessageBox.Show(query);
command.CommandText = query;
command.ExecuteNonQuery();
con.Close();
I keep getting the error:
" System.Data.OleDbException: 'Syntax error in UPDATE'"
This error is occuring in the line:
command.ExecuteNonQuery();
To clarify what Hossein has answered, when you are building your query command by adding strings together, you are wide-open to SQL-injection. Please read up on it some to protect your future development.
With reference to using "parameters". This is basically referring to a place-holder value for the query, like an "insert here" instead of you hard adding parts to the query like you were wrapping single quotes before and after the values for the password and user name.
Looking at your original query
"UPDATE tbl_users SET password = '" + test + "' WHERE username = '" + txtLoginUsername.Text + "'";
What if someone put in values of
Password: What's Up
Username: O'Conner
Your final query command when concatenated with your approach would create a value
UPDATE tbl_users SET password = 'What's Up' WHERE username = 'O'Conner'
See how the literal values have now screwed-up the string from its intent.
By using the "#" values, this is telling the SQL that hey... there will be another value coming along by the name provided, please use THAT value here. In some databases, they dont use named parameters, but "?" single character instead as a place-holder and you have to add the parameters in the exact order as they appear in the statement you are trying to prepare.
One other thing of personal preference. If your column name is UserName in I would use a parameter name like "#parmUserName" so you know it is EXPLICITLY the parameter and not accidentally just doing UserName = UserName and not get the results. A few more characters, but obvious what its purpose and where coming from works.
Now, how is that applied? Take a look again at Hossein's answer. Notice the two
command.Parameters.AddWithValue("#password", "test");
command.Parameters.AddWithValue("#username", txtLoginUsername.Text);
This is where the parameters are added to the command object. Stating, where you see the #password, use the following value I am putting here, same with #username.
Good luck going forward.
Use this syntax
Use bracket for password in query
because password is reserved word
link List of reserved world
using (var connection = new OleDbConnection("Your Connection String"))
{
var query = "UPDATE tbl_users SET [password] = #password WHERE username = #username";
using (var command = new OleDbCommand(query, connection))
{
connection.Open();
command.Parameters.AddWithValue("#password", "test");
command.Parameters.AddWithValue("#username", txtLoginUsername.Text);
command.ExecuteNonQuery();
}
}
I create an application using c# , In my authentification interface , i have a test control , i want to know profile user .
My database contains table named user which contains 4 columns
(id_user,name ,mail, profile)
Here is my code
public string profil_user(string login)
{
SqlConnection conn = new database().connect_user();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select profile from user where name = '" + login + "';";
SqlDataReader s = cmd.ExecuteReader();
if (s.Read())
{
return ( s.GetString(3));
}
else{return ("false"); }
}
but i have an exception in s.GetString(3)
system.IndexOutOfRange : index was outside the bounds of the array
You're only selecting a single field (profile) but then you're trying to select the 4th field (index 3) here:
return ( s.GetString(3));
In addition to just returning s.GetString(0) I would strongly advise you to:
Use parameterized SQL - always do this, to prevent SQL injection attacks, make your code more readable, and prevent unexpected text conversion problems
Either throw an exception or return null if the profile isn't found, instead of returning the string "false"
Use using statements for disposable things like SqlCommand, SqlConnection and SqlDataReader to ensure that you clean up resources appropriately
Start following .NET naming conventions to make your code more idiomatic
So something like:
public string GetUserProfile(string login)
{
string sql = select profile from user where name = #login";
// I assume Connect() returns an *open* connection?
using (var conn = new Database().Connect())
{
using (var command = new SqlCommand(sql, conn))
{
command.Parameters.Add("#login", SqlDbType.NVarChar).Value = login;
using (var reader = command.ExecuteReader())
{
// If it's an error (code failure) for there to be no matching profile,
// you may want to throw an exception instead.
return s.Read() ? s.GetString(0) : null;
}
}
}
}
So you want the fourth row, not the fourth column which you try to access with s.GetString(3):
int rowNum = 0;
while(s.Read())
{
if(++rowNum == 4)
{
return s.GetString(0);
}
}
return "false";
However, it is a bit strange to access the fourth row when you don't use an Order By. You should also only return the row that you want with the correct sql query.
You are also open for sql injection if you use string concatenation here:
cmd.CommandText = "select profile from user where name = '" + login + "';";
Use sql parameters:
cmd.CommandText = "select profile from user where name = #login";
cmd.Parameters.Add("#login", SqlDbType.VarChar).Value = login;
have 4 columns not rows
Ok, so you instead want the fourth column. Why don't you use the name instead?
Since you only select the profile-column(the fourth), you could simply use GetString(0). But you could also select all columns and then determine the correct index with GetOrdinal:
int profileColumnIndex = s.GetOrdinal("profile");
return s.GetString(profileColumnIndex);
This is useful if you don't control the query or it might be changed in future.
You are selecting only 1 field, thus index 3 is out of bounds. It also very important to Use parameters. Try:
cmd.CommandText = "select profile from user where name = #login;";
cmd.Parameters.Add("#login, SqlDbType.NVarChar).Value = login;
SqlDataReader s = cmd.ExecuteReader();
while (s.Read())
{
return s[0].ToString();
}
The parameter for SqlDataReader.GetString should be the column index. You're only selecting one column so you get an exception.
Because you do not have all the fields in your select list
Change the SQL to:
select id_user,name ,mail, profile from user where name = '" + login + "';
Ok, so to update. I have spoken to my professor who said that worrying about encrypted passwords/sql injection etc will wait until next term. For now, I should concentrate on the basics (no login granted if any (or both) fields are left empty, no user can login with their password but another users username etc.) I have now condensed my query into one, to check for username and password together, this prevents a login using a combination of one users password and anothers username or vice versa.
The code also won't log in if either one or both fields are left empty. My issue now is that my script alerts aren't popping up correctly. If both fields are left empty, it won't log in but it also won't have the script alert message pop-up. Same with a successful login, it will take you to the next page but won't popup with the welcome message. Can anyone tell me why? I have updated my code here to show how it looks now. Thanks!
protected void loginButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(userText.Text) || string.IsNullOrEmpty(passText.Text)) return;
{
Response.Write("<script>alert('Details are incorrect, please try again');</script>");
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["newregDBConnectionString"].ConnectionString);
conn.Open();
var checkUser = "select count(*) from parent " +
"where parentID='" + userText.Text + "' " +
"and password='" + passText.Text + "' ";
SqlCommand com = new SqlCommand(checkUser, conn);
int temp = Convert.ToInt32(com.ExecuteScalar().ToString());
conn.Close();
if (temp == 1)
{
conn.Open();
string checkPassword = "select password from parent where password='" + passText.Text + "'";
SqlCommand passCom = new SqlCommand(checkPassword, conn);
var obj = passCom.ExecuteScalar();
string password = obj?.ToString().Trim();
if (password == passText.Text)
{
Session["New"] = userText.Text;
Response.Write("<script>alert('Details are correct, welcome');</script>");
Response.Redirect("Payment.aspx");
}
else
{
Response.Write("<script>alert('Details are incorrect, please try again');</script>");
userText.Text = "";
passText.Text = "";
}
}
else
{
Response.Write("<script>alert('Details are incorrect, please try again');</script>");
userText.Text = "";
passText.Text = "";
}
conn.Close();
}
}
}
}
On the second query you only check passwords, not the username. So if there is anybody with an empty password, then everybody is let in with an empty password.
Doing two queries is not needed, it simply is better to do it all in one go:
var sql = "select count(*) from parent " +
"where parentID='" + userText.Text + "' " +
"and password='" + passText.Text + "' ";
There are several other things to improve, e.g.:
What if either text contains a single quote...(answer: the query throws an error, or worse you get SQL injection problems)
What if hackers manage to copy your database...(answer: then they know ALL passwords, because there is no hashing being done)
But I guess that is for a later moment / different question.
string password = obj?.ToString().Trim();
If obj is null, then the above expression will result in an empty string. Therefore when you:
if (password == passText.Text)
The above will succeed when passText.Text is also an empty string.
As an aside, you really should not be storing a plain text password either.
Maybe just check at the beginning ? :
protected void loginButton_Click(object sender, EventArgs e)
{
if ( string.IsNullOrEmpty(userText.Text) || string.IsNullOrEmpty(passText.Text)) return;
// rest of the code ...
}
Aside from the above, you should make use of the SqlCommand object and use SqlParameter for safety.
instead of yours :
string checkUser = "select count(*) from parent where parentID='" + userText.Text + "'";
SqlCommand com = new SqlCommand(checkUser, conn);
you can do :
string checkUser = "select count(*) from parent where parentId=#userName";
SqlParameter param = new SqlParameter("#userName", userText.Text);
SqlCommand com = new SqlCommand(checkUser, conn);
com.Parameters.Add(param);
Sidenote :
To get rid of the problems #Sefe pointed out you can just check both ( password and username ) in one query :
string checkUser = "select [enter_some_column_name_here] from parent where parentId=#userName and password=#userPass";
SqlParameter paramUsername = new SqlParameter("#userName", userText.Text);
SqlParameter paramPassword = new SqlParameter("#userPass", passText.Text);
SqlCommand com = new SqlCommand(checkUser, conn);
com.Parameters.Add(paramUsername);
com.Parameters.Add(paramPassword);
But that's still not enough. You're not encrypting user password in database and you're trying to compare raw user password. To fix this you should encrypt passwords before entering them into database and then compare encrypted versions of passwords :
byte[] buffer = Encoding.UTF8.GetByes(passText.Text);
SqlParameter paramPassword = null;
using ( SHA512 sha= new SHA512Managed())
{
byte[] hash = sha.ComputeHash(buffer);
StringBuilder builder= new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
builder.Append(hash[i].ToString("x2"));
}
paramPassword = new SqlParameter("#userPass", builder.ToString());
}
So being aware of encryption problem you should change this line :SqlParameter paramPassword = new SqlParameter("#userPass", passText.Text); into above piece of code.
I dont think you need two queries for this. You can do the same in just one:
Disclaimer: This code is unsafe and it just pretends to answer a specific question. Dont manage authentication like this.
"select count(*) from parent where parentID='" + userText.Text + "' and password='" + passText.Text + "'"
If this query returns 1 the user could be authenticated.
Annother tips you should consider to improve your code:
SqlConnection implements IDisposable, wich means it can release for you unused resources when no longer needed by enclosing it in a using statement. This forces the connection to automatically close, even if an exception occurs. You can see examples here:
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection(v=vs.110).aspx
I don't know what are the security requirements for this application, but appart from the sql injection problem, it is not generally a good idea to store plain-text user passwords in a database. You should consider using an authentication framework to manage these problems for you, like ASP net Membership:
https://msdn.microsoft.com/en-us/library/tw292whz.aspx
I hope this helps. Cheers!
You are not checking for a specific username/password combination. You are checking first if a user with a username exists:
string checkUser = "select count(*) from parent where parentID='" + userText.Text + "'";
SqlCommand com = new SqlCommand(checkUser, conn);
And then you are checking if any user with a specifc password exists:
string checkPassword = "select password from parent where password='" + passText.Text + "'";
SqlCommand passCom = new SqlCommand(checkPassword, conn);
So you just need any user without a username and any (other or the same) user without a password in the DB. Also, anyone can create a user account and use his password to log in as any other user.
You need to query for a combination of both, username and password.
There are two other dangerous issues in your code:
Never store passwords directly in your DB.
Never, ever, use the text of your text boxes directly in your SQL query.
This combination will make it ridiculously easy for even a newbie hacker to log in without requiring a password (or do even worse with your DB).
Maybe you should check both, username and password at same query
select count(*) from parent where parentID='" + userText.Text + "' AND password='" + passText.Text + "'"
I tried to update a paragraph from mysql table,but i got error like this
"You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 's first-ever super-villainess."
My mysql Query
cmd.CommandText = "UPDATE `moviemaster` SET `Runtime`='" + runtime + "',`DateMasterId`='" + dateid + "',`Trailer`='" + trailer + "',`Synopsis`='" + synopsis + "' WHERE `MovieMasterId`='" + movieid + "'";
I got error in 'synopsis',it's a big data containing a large paragraph.If i romove 'Synopsis' section from the query,everything working fine.What exactly the problem.How can i resolve this?
#SonerGönül:Ok,fine.. then please show me an example of parameterised
query
Sure. I also wanna add a few best practice as well.
Use using statement to dispose your connection and command automatically.
You don't need to escape every column with `` characters. You should only escape if they are reserved keywords for your db provider. Of course, at the end, changing them to non-reserved words is better.
Do not use AddWithValue method. It may generate upexpected and surprising result sometimes. Use Add method overload to specify your parameter type and it's size.
using (var con = new SqlConnection(conString))
using(var cmd = con.CreateCommand())
{
cmd.CommandText = #"UPDATE moviemaster
SET Runtime = #runtime, DateMasterId = #dateid, Trailer = #trailer, Synopsis = #synopsis
WHERE MovieMasterId = #movieid";
cmd.Parameters.Add("#runtime", MySqlDbType.VarChar).Value = runtime; ;
cmd.Parameters.Add("#dateid", MySqlDbType.VarChar).Value = dateid;
cmd.Parameters.Add("#trailer", MySqlDbType.VarChar).Value = trailer;
cmd.Parameters.Add("#synopsis", MySqlDbType.VarChar).Value = synopsis;
cmd.Parameters.Add("#movieid", MySqlDbType.VarChar).Value = movieid;
// I assumed your column types are VarChar.
con.Open();
cmd.ExecuteNonQuery();
}
Please avoid using inline query. Your database can be subjected to SQL Injection. See this example, on what can be done using SQL Injection.
And use paramterized query instead. Here is the example taken from here. This way, even if your string has special characters, it will not break and let you insert/update/select based on parameters.
private String readCommand = "SELECT LEVEL FROM USERS WHERE VAL_1 = #param_val_1 AND VAL_2 = #param_val_2;";
public bool read(string id)
{
level = -1;
MySqlCommand m = new MySqlCommand(readCommand);
m.Parameters.AddWithValue("#param_val_1", val1);
m.Parameters.AddWithValue("#param_val_2", val2);
level = Convert.ToInt32(m.ExecuteScalar());
return true;
}
and finally, your query will become
cmd.CommandText = "UPDATE `moviemaster` SET `Runtime`= #param1,`DateMasterId`= #dateid, `Trailer`= #trailer,`Synopsis`= #synopsis WHERE `MovieMasterId`= #movieid";
cmd.Parameters.AddWithValue("#param1", runtime);
cmd.Parameters.AddWithValue("#dateid", dateid);
cmd.Parameters.AddWithValue("#trailer", trailer);
cmd.Parameters.AddWithValue("#synopsis", synopsis);
cmd.Parameters.AddWithValue("#movieid", movieid);
I'm working on a C# project with some data bases. I'm getting an error when executing the following function:
//Returns true if the username and password are correct. Otherwise it returns false.
public bool LogInto(string name, string pass, OleDbConnection cnx)
{
DataTable res = new DataTable();
OleDbDataAdapter adp = new OleDbDataAdapter("SELECT User,Password FROM UserPassword WHERE (User='"+name+"' AND Password='"+pass+"')", cnx);
adp.Fill(res);
bool found = false;
String user = Convert.ToString(res.Rows[0]["User"]);
String password = Convert.ToString(res.Rows[0]["Password"]);
if (name==user && pass==password)
found = true;
return found;
}
So this is the full function, however I'm getting an error, I just replaced && with AND. But it still doesn't work. I'm getting ("There was an error parsing the query. // Token number, token line offset, token in error.
What's wrong with it? I had the same function but instead of taking just one row from the data table, it took the whole table and with a loop it looked the row we were looking for. However, I'm trying to do this one, just taking the row we need, because it is more efficient.
Could you guys help me? I can't find my mistake.
Thank you so much
You have some issues with the query:
The and operator in SQL is and, not &&
The query is WIDE OPEN FOR SQL INJECTION ATTACKS. You have to escape the strings to be correctly interpreted as string literals.
You can do it like this:
string query =
"SELECT User, Password FROM UserPassword WHERE Username = '" +
name.Replace("\\", "\\\\").Replace("'", "\\'") +
"' and Password = '" +
pass.Replace("\\", "\\\\").Replace("'", "\\'") +
"'";
Note: This way to escape the strings is specific to MySQL. Each database have a different set of characters that needs to be escaped, and in different ways.
If possible you should use a parameterised query instead of concatenating string into the query. That makes it easier to get it correct.
First please use parameterized one like this, with IDisposable inherited
using(SqlCommand cmd = new SqlCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = #""SELECT up.User, up.Password FROM dbo.UserPassword up WHERE up.Username = #Param1" AND Password = #Param2;
cmd.Parameters.Add("#Param1", SqlDbType.Varchar).Value = 'ABC';
.............
}
second try to encrypt it or hash it, there are lot of information about hashing and encrytion on web