C# Oracle table issue - c#

I've got a problem with my ASP.NET application when I'm trying to log in a user. The issue is that when I'm trying to run the query, an exception gets thrown which says the tale name is invalid. It's because the table is called USER, which is a part of SQL.
I'm not in a position where I can change the table name.
public bool LoginUser(string username, string password)
{
//Database Connectie maken
DBConnectionOpen();
string query = #"SELECT NICKNAME, PASSWORD FROM " + "'USER'" + "WHERE NICKNAME = '" + username + "'";
bool result = false;
try
{
OracleCommand command = new OracleCommand(query, conn);
OracleDataReader reader = command.ExecuteReader();
Console.WriteLine("*Query Uitvoeren*");
reader.Read();
if (username + password == reader.GetString(0) + reader.GetString(1))
{
result = true;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
return result;
}

Whomever named the table "USER" should have db privs removed, but I think you just need to add double quotes around the table name:
select * from "USER" where ...
Note that its case sensitive when you add the double quotes, so if the table is named User you'd need "User" instead of "USER"

Thanks for all the response, but I finally figured it out.
What the query should have been:
string query = #"SELECT NICKNAME, ""PASSWORD"" FROM ""USER"" WHERE NICKNAME = '" + username + "'";

You are querying on the string value 'USER'.
You should use
string query = #"SELECT NICKNAME, PASSWORD FROM [USER] WHERE NICKNAME = '" + username + "'";
This will query on the table called USER. In SQL normally you use brackets to indicate you are querying on an object if what you mean can be ambiguous.
The concatenation of the table name as a string is unnecessary so I left it out. If you change it to a variable it can be useful.
In addition instead of concatenating username maybe you should also use alternative for Oracle what is called SqlParameter for SQL Server, to avoid SQL injection.

Try to correct your SQL statement like the following:
string query = "SELECT NICKNAME, PASSWORD FROM [USER] WHERE NICKNAME = '" + username + "'";
Also, if you are using SQL reserved word (e.g. DATE) as a Column name, then enclose it in angular brackets (like [DATE]) in your SQL statement.
Hope this may help.

Related

Syntax error in UPDATE for C# using Oledb

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();
}
}

What is wrong with my code, meaning that no details entered still logs the user in?

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 + "'"

Getting a String from a value in Mysql in C#

i have the following table in MySql :
ID Name
1 Google
2 Yahoo
3 Facebook
4 Whatever
I have a textfield that when someone writes something and presses a button it stores this value in a string. This string is the Name of the above table. Then i have my code about selecting the id referred to that name. Ex, if the user enters Facebook i will find that the ID = 3. this is the code :
public bool FindCompanyID(string companyName)
{
return ExecQuery("select id from companies where name=#name",
cmd =>
{
cmd.CommandText = "SELECT id from companies WHERE name ='" + companyName + "'";
return cmd;
});
}
I want someone to show me a sample of code about the following : Saving to a string the " id " . if the ID in the database = 2 i want to make a
int Company_Number_ID
that i will use. How can i get the string to read the specified value from the database?
I am guessing your return type is bool to check whether the DDL statements were executed successfully.
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT id from companies WHERE name ='" + companyName + "'";
try
{
dbConn.Open();
Company_Number_ID = (Int32)cmd.ExecuteScalar();
} catch (Exception e) {
//Exception occured. Handle it here
}
Note: cmd.Parameters.AddWithValue("#companyName",companyName).
this is more secure
Edit: As pointed out in the comment by user3185569 , ExecuteScalar is better if you are sure it'll return only one row. But since no such information was provided. I did not consider that.
You can use ExecuteScalar directly like this.
Company_Number_ID = (Int32)cmd.ExecuteScalar();

error in query in asp.net [duplicate]

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

Can't Add Parameter To Query String

I need to have a second copy of a MS Access table that will be saved in a network drive. And since splitting is not an option because it drastically slows the application down, I decided to just manually "merge" the data after a certain user action like clicking an exit button.
I have this query string
public const string MERGETOMAIN = #"INSERT INTO tbl_name (UserID, ...)" +
" IN 'C:\Users\nathan\Desktop\copy.accdb' SELECT TOP 1 UserId, ... " +
" FROM tbl_name WHERE UserID = #currentUser ORDER BY ROWID DESC";
...and it works when I do this:
using (OleDbCommand cmd = new OleDbCommand(Helpers.Queries.MERGETOMAIN, mergeConn))
{
cmd.Parameters.AddWithValue("#currentUser", currentUserID);
cmd.ExecuteNonQuery();
}
But, as you notice, the path to the copy is hardcoded. I wanted it to be dynamic so I tried using a parameter like I always do, so I replaced it with a question mark:
public const string MERGETOMAIN = #"INSERT INTO tbl_name (UserID, ...)" +
" IN ? SELECT TOP 1 UserId, ... " +
" FROM tbl_name WHERE UserID = #currentUser ORDER BY ROWID DESC";
But this results in the following error:
Your network access was interrupted. To continue close the database and then open it again.
So instead of a question mark, I used #parameterName. But, when I do, I get the following error:
The file "foo\foo\#parameterName" cannot be found.
The weird thing is, the other paremeter, #currentUser, is working just fine.
I'm not really sure what is happening here, but the only thing that works right now is to hardcode the path. I tried looking through similar questions but no dice.
Any idea will be greatly appreciated.
Thank you.
You can write a method which creates the string for you.
public string getMergeToMain(string path)
{
string strRet;
if (path != null)
{
strRet = #"INSERT INTO FSO_LogSheet (UserID, ...)" +
" IN '" + path + "' SELECT TOP 1 UserId, ... " +
" FROM FSO_LogSheet WHERE UserID = #currentUser ORDER BY ROWID DESC";
return strRet;
}
else
{ //Error, not agood habit to return null...
return null;
}
}
With the method parameter "path", you can set the path dynamically.
You can call it for example by
OleDbCommand cmd = new OleDbCommand(fooClass.getMergeToMain(#"C:\users\bar.accdb"), mergeConn)
I assume that you know the difference between public, private and static methods, so please do not forget to set it right for your own needs.

Categories