I want to create a User and Insert to an exist table with a mysql query.
I have this in C#:
using (OdbcCommand cmd6 = new OdbcCommand("INSERT INTO users (id,Name,login,pass) VALUES ('" + textboxID.Text + "','" + textboxNAME.Text + textboxLOGIN.Text + "','" + textboxPASS.Text + "' )", conn6))
I want to get the pass from textboxPASS.Text and inserts as encrypted, because now it inserts as text.
Note.-
If I put "pass123456" in my textboxPASS...It take it and inserts as text: "pass123456".
And when I see the table, the others already existing users have encrypted passwords. (around 40 numeric characters).
But my new user has that field as text "pass123456".
I hope you can help me.
Thanks!
The SQL is doing what it is told. If you want to run some cryptographic operation on the data first, you must do that:
// note using ? since ODBC has poor support for named parameters, IIRC
using (OdbcCommand cmd = new OdbcCommand(
"INSERT INTO users (id,Name,login,pass) VALUES (?,?,?,?)", conn))
{
// this is most likely a hash op, and probably involves salt of some kind
var cryptoPass = SomeCryptoOperation(..., textboxPASS.Text);
cmd.Parameters.AddWithValue("id", textboxID.Text);
cmd.Parameters.AddWithValue("name", textboxNAME.Text);
cmd.Parameters.AddWithValue("login", textboxLOGIN.Text);
cmd.Parameters.AddWithValue("pass", cryptoPass);
cmd.ExecuteNonQuery();
}
Just call the encrypt function eg.
using (SqlCommand cmd6 = new SqlCommand("INSERT INTO Users VALUES(#Username, #Password)"))
{
cmd6.CommandType = CommandType.Text;
cmd6.Parameters.AddWithValue("#Username", txtUsername.Text.Trim());
cmd6.Parameters.AddWithValue("#Password", Encrypt(txtPassword.Text.Trim()));
for more advanced encryption check for AES functions
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();
}
}
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 + "'"
string sql = "insert into tblmain values('" + txtName.Text + "','" + txtPost.Text + "','" + DropDownList1.SelectedItem + "')";
If the user inserts My name's first later is D ! in txtPost, then it gives error that 's are not allowed.
Can you please send me the code to accept this type of character from textbox in .net (C#).
You sample is the book example of SQL injection in most pure form. ' closes the previous quote and the rest of SQL command is interpreted differently from what you expect.
There is no excuses to not using parametrized queries when dealing with non-hardcoded values and SqlConnection directly.
Also check these articles for mre details. Approximate sample (need more fields and not showing exception handling):
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand("insert into tblmain values(#name")", connection);
command.Parameters.Add("#name", SqlDbType.String);
command.Parameters["#name"].Value = customerID;
connection.Open();
Int32 rowsAffected = command.ExecuteNonQuery();
Console.WriteLine("RowsAffected: {0}", rowsAffected);
}
The second problem you may hit is if you pick wrong field type for the text - to be able to store characters you want you need Unicode string. Check out C#: DbType.String versus DbType.AnsiString post for details.
I have a form which inserts data into a database.
There are certain fields that are not always going to be needed.
When I leave these blank in my code I get a error saying.
Column name or number of supplied values does not match table
definition.
This is how I have the database setup. SQL Server 2008
[youthclubid]
[youthclubname]
[description]
[address1]
[address2]
[county]
[postcode]
[email]
[phone]
Here is the code that I have connecting to the database and doing the insert.
connection.Open();
cmd = new SqlCommand("insert into youthclublist values ('" + youthclubname.Text + "', '" + description.Text + "','" + address1.Text + "','" + address2.Text + "', '" + county.Text + "', '" + postcode.Text + "', '" + email.Text + "', '" + phone.Text + "')", connection);
cmd.ExecuteNonQuery();
You have two major problems:
1) concatenating together your SQL statement is prone to SQL injection attacks - don't do it, use parametrized queries instead
2) You're not defining which columns you want to insert in your table - by default, that'll be all columns, and if you don't provide values for all of them, you'll get that error you're seeing.
My recommendation: always use a parametrized query and explicitly define your columns in the INSERT statement. That way, you can define which parameters to have values and which don't, and you're safe from injection attacks - and your performance will be better, too!
string insertStmt =
"INSERT INTO dbo.YouthClubList(Youthclubname, [Description], " +
"address1, address2, county, postcode, email, phone) " +
"VALUES(#Youthclubname, #Description, " +
"#address1, #address2, #county, #postcode, #email, #phone)";
using(SqlConnection connection = new SqlConnection(.....))
using(SqlCommand cmdInsert = new SqlCommand(insertStmt, connection))
{
// set up parameters
cmdInsert.Parameters.Add("#YouthClubName", SqlDbType.VarChar, 100);
cmdInsert.Parameters.Add("#Description", SqlDbType.VarChar, 100);
.... and so on
// set values - set those parameters that you want to insert, leave others empty
cmdInsert.Parameters["#YouthClubName"].Value = .......;
connection.Open();
cmdInsert.ExecuteNonQuery();
connection.Close();
}
The first major issue is that you are concatenating inputs in the query. This makes your application highly vulnerable to SQL Injection. Do not do this. Use a parametrized query.
The regular syntax for insert statement is like this:
Insert into <TableName> (Col1, Col2...Coln) values (val1, val2...valn)
If you need to insert only a selected set of columns, you need to provide the list of columns you are inserting data into in the column list.
If you do not specify the column list, the indication is that you are inserting data to each one of them.
So you may check for the input and if it is not there, you may omit the respective column.
The other better way is use a stored proc. That will ease out the issue.
This not way to do the code you make use of SqlParameter for this kind of statement.
So your code something like
SqlConnection thisConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["Northwind_ConnectionString"].ConnectionString);
//Create Command object
SqlCommand nonqueryCommand = thisConnection.CreateCommand();
try
{
// Create INSERT statement with named parameters
nonqueryCommand.CommandText = "INSERT INTO Employees (FirstName, LastName) VALUES (#FirstName, #LastName)";
// Add Parameters to Command Parameters collection
nonqueryCommand.Parameters.Add("#FirstName", SqlDbType.VarChar, 10);
nonqueryCommand.Parameters.Add("#LastName", SqlDbType.VarChar, 20);
nonqueryCommand.Parameters["#FirstName"].Value = txtFirstName.Text;
nonqueryCommand.Parameters["#LastName"].Value = txtLastName.Text;
// Open Connection
thisConnection.Open();
nonqueryCommand.ExecuteNonQuery();
}
catch (SqlException ex)
{
// Display error
lblErrMsg.Text = ex.ToString();
lblErrMsg.Visible = true;
}
finally
{
// Close Connection
thisConnection.Close();
}
You need to tell SQL server that which field you want to insert like
insert into youthclublist(youthclubid, youthclubname, ....) values ('" + youthclubname.Text + "', '" + description.Text + "'.....
and you are fine.
Though new into programming, the easiest way i know to insert into a database is to create a "save" stored procedure, which is then called up through your connection string. Believe me, this is the best way.
Another way around is to use LINQ to SQL. i found this much more easier. Follow this steps.
Add a new LINQ to SQL Classes to your project. Make sure the file extension is '.dbml'. Name it your name of choice say "YouthClub.dbml"
Connect your Database to Visual Studio using the Server Explorer
Drag your table to the OR Designer.(I'm not allowed to post images).
You can now save to the Database with this code
//Create a new DataContext
YouthClubDataContext db = new YouthClubDataContext();
//Create a new Object to be submitted
YouthClubTable newYouthClubRecord = new YouthClubTable();
newYouthClubRecord.youthlubname = txtyouthclubname.Text;
newYouthClubRecord.description = txtdescription.Text;
newYouthClubRecord.address1 = txtaddress1.Text;
newYouthClubRecord.address2 = txtaddress2.Text;
newYouthClubRecord.county = txtcounty.Text;
newYouthClubRecord.email = txtemail.Text;
newYouthClubRecord.phone = txtphone.Text;
newYouthClubRecord.postcode = txtpostcode.Text;
//Submit to the Database
db.YouthClubTables.InsertOnSubmit(newYouthClubRecord);
db.SubmitChanges();
Hope this time I have given a real answer
I want to delete some record from table ,by running this Query in C# is it Correct or not,
Please help me
SqlCommand cmdRe = new SqlCommand("insert into msisdn_master SELECT * from tblDeactive
where msisdn in (" + str_MSISDN + ")", cn);
SqlCommand cmdRed = new SqlCommand("delete from tblDeactive where msisdn in ("+str_MSISDN+")", cn);
cmdRe.CommandType = CommandType.Text;
cmdRed.CommandType = CommandType.Text;
note : str_MSISDN is the StringBuilder which stores the Number which is inserted in TextField.
You should be using proper SQL parameters. NEVER use string building since that leaves you open for injection attacks.
Read this tutorial to learn how to add parameters to SqlCommands.