I am trying to change the user password. I am not able to update the password :(. The message i am getting is password changed where as its not getting changed. .
My code is as follow.. Please if anyone can suggest where i am going wrong . I am just a beginner ...
protected void Button1_Click(object sender, EventArgs e)
{
DatabaseLayer data = new DatabaseLayer();
string username = Session["Authenticate"].ToString();
string password = TextBox1.Text;
string newpass = TextBox2.Text;
string confirm = TextBox3.Text;
string flag = "";
if (newpass.ToString() == confirm.ToString())
{
flag = data.passwordChange(username, password, newpass);
Literal1.Text = flag.ToString();
}
else
{
Literal1.Text = "New Password does not match the Confirm Password ";
}
}
The above click event must change my password, and the function passwordChange is as follows..
public string passwordChange(string username, string password, string newPasswd)
{
string SQLQuery = "SELECT password FROM LoginAccount WHERE username = '" + username + "'";
string SQLQuery1 = "UPDATE LoginAccount SET password = ' " + newPasswd + " ' WHERE username = ' " + username + "'";
SqlCommand command = new SqlCommand(SQLQuery, sqlConnection);
SqlCommand command1 = new SqlCommand(SQLQuery1, sqlConnection);
sqlConnection.Open();
string sqlPassword = "";
SqlDataReader reader;
try
{
reader = command.ExecuteReader();
if (reader.Read())
{
if (!reader.IsDBNull(0))
{
sqlPassword = reader["password"].ToString();
}
}
reader.Close();
if (sqlPassword.ToString() == password.ToString())
{
try
{
int flag = 0;
flag = command1.ExecuteNonQuery();
if (flag > 0)
{
sqlConnection.Close();
return "Password Changed Successfully";
}
else
{
sqlConnection.Close();
return "User Password could not be changed";
}
}
catch (Exception exr)
{
sqlConnection.Close();
return "Password Could Not Be Changed Please Try Again";
}
}
else
{
sqlConnection.Close();
return "User Password does not Match";
}
}
catch (Exception exr)
{
sqlConnection.Close();
return "User's Password already exists";
}
}
I had put a break point near
if(flag>0)
it still shows that executeNonquery aint returning the updated rows value and also in the Back end of SQL server, its not changing,
Please if anyone could correct me... Should i use other execute command or something?
I am doing this with VS 2008 and SQL server 2005..
1: It's your spacing between your single and double quotes: (Like: ' " + username + " ')
2) You are begging for SQL Injection.
Try this in your PasswordChange method:
public string PasswordChange(string userName, string oldPass, string newPass)
{
using(SqlConnection sqlConnection = new SqlConnection(
ConfigurationManager.ConnectionStrings["LoginDb"].ConnectionString))
{
string sqlToConfirmOldPass =
"SELECT password FROM LoginAccount WHERE username = #userName";
string sqlToUpdatePassword =
"UPDATE LoginAccount SET password = #newPass WHERE username = #userName";
SqlCommand confirmOldPass = new SqlCommand(sqlToConfirmOldPass, sqlConnection);
confirmOldPass.Parameters.AddWithValue("#userName", userName);
SqlCommand updatePassword = new SqlCommand(sqlToUpdatePassword, sqlConnection);
updatePassword.Parameters.AddWithValue("#newPass", newPass);
updatePassword.Parameters.AddWithValue("#userName", userName);
[Rest of your code goes here]
}
}
I also didn't see where you set your SqlConnection, so I've added a line for that. You'll need to modify it according to your needs.
Maybe try this code instead.
public string passwordChange(string username, string password, string newPasswd)
{
string SQLQuery = "SELECT password FROM LoginAccount WHERE username = #username";
string SQLQuery1 = "UPDATE LoginAccount SET password = #newPassword WHERE username = #username";
SqlCommand command = new SqlCommand(SQLQuery, sqlConnection);
command.Parameters.AddWithValue("#username", username);
SqlCommand command1 = new SqlCommand(SQLQuery1, sqlConnection);
command1.Parameters.AddWithValue("#username", username);
command1.Parameters.AddWithValue("#newPassword", newPasswd);
sqlConnection.Open();
string sqlPassword = "";
SqlDataReader reader;
try
{
reader = command.ExecuteReader();
if (reader.Read())
{
if (!reader.IsDBNull(0))
{
sqlPassword = reader["password"].ToString();
}
}
reader.Close();
if (sqlPassword.ToString() == password.ToString())
{
try
{
int flag = 0;
flag = command1.ExecuteNonQuery();
if (flag > 0)
{
sqlConnection.Close();
return "Password Changed Successfully";
}
else
{
sqlConnection.Close();
return "User Password could not be changed";
}
}
catch (Exception exr)
{
sqlConnection.Close();
return "Password Could Not Be Changed Please Try Again";
}
}
else
{
sqlConnection.Close();
return "User Password does not Match";
}
}
catch (Exception exr)
{
sqlConnection.Close();
return "User's Password already exists";
}
}
If you're getting zero rows affected double check that your WHERE clause actually works. I'd bet that if you SELECTed WHERE username = '" + username + "'", you won't find the row you're looking for. That'd, at least, be the first thing I would confirm.
Related
I encountered a problem while trying to verify if a value exists in the database. I use Visual Studio 2017.
I wrote a function that checks if Username is in the database table:
protected bool userIsAdmin(string user)
{
SqlConnection con = new SqlConnection(connectionString);
con.Open();
string loginQuery = "select count(*) from AdminTable where User= #Username";
SqlCommand command = new SqlCommand(loginQuery, con);
command.Parameters.AddWithValue("#Username", user);
user = user.Trim();
int rows;
rows = (int)command.ExecuteScalar();
if (rows != 0)
{
OutputLabel.Text = "You are logged";
return true;
}
else
{
OutputLabel.Text = "Try again";
return false;
}
}
I eliminated the probability of an outside error by calling this function like this:
if(userIsAdmin("uia94881"){...}
My database table:
enter image description here
Replace your script as below,
string loginQuery = "select count(*) from AdminTable where [User]= #Username";
because User is a built in function in SQL Server, which will give you the Database username.
SqlConnection connection = new SqlConnection("PUT YOUR CONNECTION STRING HERE");
string loginQuery = "SELECT (User) FROM AdminTable WHERE User = #Username";
SqlDataAdapter adpt = new SqlDataAdapter(loginQuery, connection);
adapt.SelectCommand.Parameters.AddWithValue("#Username", user);
DataSet usr = new DataSet();
adapt.Fill(usr)
foreach(DataRow dr in usr.Tables[0].Rows)
{
string user += usr.Tables[0].Rows[0]["User"].ToString();
}
if(user != "")
{
OutputLabel.Text = "Try again";
return false;
}
else
{
OutputLabel.Text = "You are logged";
return true;
}
Try this instead!
I'm trying to check if a username with the given passwort exists in my database, if it exists it should return true otherwise it should return false.
My current function looks like the following:
public bool user_check(string username, string password)
{
string query = "SELECT username, password from swear_tool where username='" + username + "' and password = '" + password + "'";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
if (dataReader.HasRows)
{
while (dataReader.Read())
{
return true;
}
}
else
{
return false;
}
dataReader.Close();
this.CloseConnection();
}
}
But I receive the following error message:
Error CS0161 'database_connector.user_check(string, string)': not all
code paths return a value
What am I doing wrong?
Just add a return false; at the end. Also you don't need the else return false in the inner if
public bool user_check(string username, string password)
{
string query = "SELECT username, password from swear_tool where username='" + username + "' and password = '" + password + "'";
if (this.OpenConnection())
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
if (dataReader.HasRows)
{
while (dataReader.Read())
{
return true;
}
}
dataReader.Close();
this.CloseConnection();
}
return false;
}
Also see that if you have records then you return true and never close your connection and object. Maybe do this instead:
public bool user_check(string username, string password)
{
string query = "SELECT username, password from swear_tool where username='" + username + "' and password = '" + password + "'";
bool hasRecords = false;
if (this.OpenConnection())
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
if (dataReader.HasRows)
{
while (dataReader.Read())
{
hasRecords = true;
break;
}
}
dataReader.Close();
this.CloseConnection();
}
return hasRecords;
}
last thing: look into Parameterized Queires to avoid SQL Injections
Just add a return false at the end of the method:
public bool user_check(string username, string password)
{
string query = "SELECT username, password from swear_tool where username='" + username + "' and password = '" + password + "'";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
if (dataReader.HasRows)
{
while (dataReader.Read())
{
return true;
}
}
else
{
return false;
}
dataReader.Close();
this.CloseConnection();
}
return false; //<<---- This is where it does not know what to do if any above conditions fail.
}
if this check returns false:
if (this.OpenConnection() == true)
You exit without returning anything.
Error CS0161 occurs when a function that specifies a return type in its signature contains a path through the function that does not return a value. In your case your function does not return a value when the this.OpenConnection() method returns false.
To prevent this error from being reported by the compiler, all paths should return a value:
public bool user_check(string username, string password)
{
string query = "SELECT username, password from swear_tool where username='" + username + "' and password = '" + password + "'";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
if (dataReader.HasRows)
{
while (dataReader.Read())
{
return true;
}
}
else
{
return false;
}
dataReader.Close();
this.CloseConnection();
}
return false;
}
I take this opportunity to let you know about SQL injection
Your code is vulnerable to SQL injection because you're concatenating user input into your query. You're encouraged to use parameterized queries, for more information about this topic check out this link
That's because you are writing your return inside if while blocks only.Besides I suggest you use parameterized query
public bool user_check(string username, string password){
string query = "SELECT username, password From swear_tool Where "+
"username=#uname and password=#password";
if (this.OpenConnection() == true){
using(MySqlCommand cmd = new MySqlCommand(query, connection)){
cmd.Parameters.AddWithValue("#uname",usename);
cmd.Parameters.AddWithValue("#password",password);
using(MySqlDataReader dataReader = cmd.ExecuteReader()){
if (dataReader.HasRows){
while(dataReader.Read()){
return true;
}
}
}
}
this.CloseConnection();
}
return false;
}
Nice and Clean and Safe and Shorter
The previous answer do not close the connection when a user exists.
Try this:
public bool user_check(string username, string password)
{
string query = "SELECT username, password from swear_tool where username='" + username + "' and password = '" + password + "'";
if (this.OpenConnection())
{
try
{
using (MySqlCommand cmd = new MySqlCommand(query, connection))
{
using (MySqlDataReader dataReader = cmd.ExecuteReader())
{
if (dataReader.HasRows)
{
while (dataReader.Read())
{
return true;
}
}
}
}
}
finally
{
this.CloseConnection();
}
}
return false;
}
The user and password are correct but are returning as incorrect. What can it be?
Importantly, the password and encrypted in md5.
public static bool logarUsuario(string user, string pw)
{
try
{
const string checkUser = "SELECT COUNT(*) FROM tbUsuario WHERE userName = '#user'";
SqlConnection con = Banco.con();
con.Open();
SqlCommand cmd = new SqlCommand(checkUser, con);
int temp = Convert.ToInt32(cmd.ExecuteNonQuery().ToString());
cmd.Parameters.AddWithValue("#user", user);
con.Close();
if (temp == 1)
{
con.Open();
string checkPw = "SELECT pw FROM tbUsuario WHERE userName = '#user'";
SqlCommand passConn = new SqlCommand(checkPw, con);
cmd.Parameters.AddWithValue("#user", user);
string password = passConn.ExecuteScalar().ToString();
Registrar criptografia = new Registrar();
if (password == pw)
{
return true;
}
}
}
catch (SqlException ex)
{
Console.WriteLine("Erro " + ex.Message);
}
return false;
}
Within the btnLogar click event:
Already checked the database and the username and password are correct, but this as incorrect password.
protected void bntLogar_Click(object sender, EventArgs e)
{
Registrar criptografia = new Registrar();
if (Login.logarUsuario(txtUser.Text, criptografia.CriptografiaMD5(txtSenha.Text)))
{
//Cria um cookie do lado do servidor
HttpCookie cookie = new HttpCookie("estado", "conectado");
//Define a validade do cookie (10 dias a partir de hoje)
cookie.Expires = DateTime.Now.AddMonths(12);
//Envia o cookie para o cliente
Response.Cookies.Set(cookie);
//Redireciona para a pagina inicial
Response.Redirect("Admin.aspx");
}
else
{
lblErro.Text = "Usuário ou Senha Incorretos";
lblErro.Visible = true;
lblErro.CssClass = "alert alert-danger";
}
}
'#user' is incorrect. Do not surround a parameter name with a single quote. It should look like
SELECT pw FROM tbUsuario WHERE userName = #user
Also MD5 is no longer considered secure, I suggest using SHA-256.
You can do this with a single SELECT statement
public static bool logarUsuario(string user, string pw)
{
const string checkUser =
#"SELECT COUNT(*) FROM tbUsuario
WHERE userName = #u AND pw = #p";
using (SqlConnection con = Banco.con())
{
con.Open();
SqlCommand cmd = new SqlCommand(checkUser, con);
cmd.Parameters.AddWithValue("#u", user);
cmd.Parameters.AddWithValue("#p", pw);
return 1 == (int) cmd.ExecuteNonQuery();
}
}
This assumes that pw is already hashed.
I am trying to create a login for users which is connected to a MySQL database. When I try logging in on the form I am greeted with the error "could not find specified column in results: password" I have some idea it may be because of my DataReader but unsure how to fix.
public class Security
{
public static string HashSHA256(string value)
{
var sha256 = System.Security.Cryptography.SHA256.Create();
var inputBytes = Encoding.ASCII.GetBytes(value);
var hash = sha256.ComputeHash(inputBytes);
var sb = new StringBuilder();
for (var i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
}
private void btnLogin_Click(object sender, EventArgs e)
{
try
{
string strConnect = "Server=***.***.***.**;Port=3306;Database=cpr_users;Uid=********;Pwd=********;";
using (MySqlConnection myConn = new MySqlConnection(strConnect))
using (MySqlCommand selectCommand = new MySqlCommand())
{
selectCommand.CommandText = "SELECT COUNT(*) FROM cpr_users.cpr_user_info WHERE username=#User and password=#Password";
selectCommand.Connection = myConn;
selectCommand.Parameters.Add("#User", MySqlDbType.VarChar).Value = txtUsername.Text;
selectCommand.Parameters.Add("#Password", MySqlDbType.VarChar).Value = txtPassword.Text;
myConn.Open();
MySqlDataReader myReader = selectCommand.ExecuteReader();
var hashedPW = Security.HashSHA256(txtPassword.Text);
var stored = myReader["password"].ToString();
Int32 count = (Int32)selectCommand.ExecuteScalar();
if (count == 1 & hashedPW == stored)
{
MessageBox.Show("Connection Successful");
}
else if (count > 1)
{
MessageBox.Show("Duplication of Username and Password... Access Denied");
}
else
{
MessageBox.Show("Incorrect Username and/or Password");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I am still learning so help is appreciated and if possible an explanation :)
private void btnLogin_Click(object sender, EventArgs e)
{
try
{
string strConnect = "Server=***.***.***.**;Port=3306;Database=cpr_users;Uid=********;Pwd=********;";
using (MySqlConnection myConn = new MySqlConnection(strConnect))
using (MySqlCommand selectCommand = new MySqlCommand())
{
var passwordHash = Security.HashSHA256(txtPassword.Text);
selectCommand.CommandText = "SELECT COUNT(*) FROM cpr_users.cpr_user_info WHERE username=#User and password=#Password";
selectCommand.Connection = myConn;
selectCommand.Parameters.Add("#User", MySqlDbType.VarChar).Value = txtUsername.Text;
selectCommand.Parameters.Add("#Password", MySqlDbType.VarChar).Value = passwordHash;
myConn.Open();
int count = (int)selectCommand.ExecuteScalar();
if (count == 1)
{
MessageBox.Show("Connection Successful");
}
else if (count > 1) // Consider adding a database constraint to prevent duplicate usernames
{
MessageBox.Show("Duplication of Username and Password... Access Denied");
}
else
{
MessageBox.Show("Incorrect Username and/or Password");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}I think you need to call Read() on your MySqlDataReader object
private void btnLogin_Click(object sender, EventArgs e)
{
try
{
string strConnect = "Server=***.***.***.**;Port=3306;Database=cpr_users;Uid=********;Pwd=********;";
using (MySqlConnection myConn = new MySqlConnection(strConnect))
using (MySqlCommand selectCommand = new MySqlCommand())
{
// You need to select all the records instead of COUNT(*)
selectCommand.CommandText = "SELECT * FROM cpr_users.cpr_user_info WHERE username=#User and password=#Password";
selectCommand.Connection = myConn;
selectCommand.Parameters.Add("#User", MySqlDbType.VarChar).Value = txtUsername.Text;
selectCommand.Parameters.Add("#Password", MySqlDbType.VarChar).Value = txtPassword.Text;
myConn.Open();
MySqlDataReader myReader = selectCommand.ExecuteReader();
// If there is a record
if(myReader.Read())
{
var hashedPW = Security.HashSHA256(txtPassword.Text);
var stored = myReader["password"].ToString();
Int32 count = (Int32)selectCommand.ExecuteScalar();
if (count == 1 & hashedPW == stored)
{
MessageBox.Show("Connection Successful");
}
else if (count > 1)
{
MessageBox.Show("Duplication of Username and Password... Access Denied");
}
else
{
MessageBox.Show("Incorrect Username and/or Password");
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Well your select command doesn't return the column password, so you can't read it.
But in reality you don't need to read it back.
Supposing that you store (as you should) the hash of the password, then pass directly the hash.
If you call ExecuteScalar and this method returns not null and > 0 then you are sure that your user has correctly identified itself
private void btnLogin_Click(object sender, EventArgs e)
{
try
{
string strConnect = "Server=***.***.***.**;Port=3306;Database=cpr_users;Uid=********;Pwd=********;";
using (MySqlConnection myConn = new MySqlConnection(strConnect))
using (MySqlCommand selectCommand = new MySqlCommand())
{
selectCommand.CommandText = #"SELECT COUNT(*)
FROM cpr_users.cpr_user_info
WHERE username=#User and password=#Password";
selectCommand.Connection = myConn;
selectCommand.Parameters.Add("#User", MySqlDbType.VarChar).Value = txtUsername.Text;
selectCommand.Parameters.Add("#Password", MySqlDbType.VarChar).Value = Security.HashSHA256(txtPassword.Text);
object result = selectCommand.ExecuteScalar();
if (result != null)
{
int count = Convert.ToInt32(result);
if(count > 0)
MessageBox.Show("Connection Successful");
else
MessageBox.Show("Incorrect Username and/or Password");
}
else
{
MessageBox.Show("Incorrect Username and/or Password");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Of course, you can't have two identical usernames. The field cpr_users.cpr_user_info.username should be defined as an UNIQUE index or as a PRIMARYKEY directly in the datatable schema.
Even if you fix your current code with something like
SELECT * FROM cpr_users.cpr_user_info WHERE username=#user and password=#password
your code will never find the match because you pass the password in clear text when you call the ExecuteReader. This means that, if you find your user then the password is stored in clear text and you cannot compare it with the hashed version returned by Security.HashSHA256. As I have said at the beginning, you should store the HASH not the clear text password.
I am not really sure, but my guess is that you are trying to get a column from a result set where it doesn't exists.
If you run your query with the correct info instead of *****
SELECT COUNT(*) FROM cpr_users.cpr_user_info WHERE username=***** and password=******
you will get a result similar to this:
Count(*)
1
So when you call:
var stored = myReader["password"].ToString();
It's trying to get a Column named 'password' but the only column in your result set is 'Count(*)'.
If you really need the count(*) function you may try:
SELECT password, COUNT(*) FROM cpr_users.cpr_user_info WHERE username=***** and password=****** group by password;
You are not return the "password" field. You are returning just a number, because of the Count(*), that is the number of records that match the criteria.
So, first you retrieve the number of users:
selectCommand.CommandText = "SELECT COUNT(*) FROM cpr_users.cpr_user_info WHERE username=#User";
selectCommand.Connection = myConn;
selectCommand.Parameters.Add("#User", MySqlDbType.VarChar).Value = txtUsername.Text;
myConn.Open();
Int32 count = (Int32)selectCommand.ExecuteScalar();
if (count != 1)
//message
After that, you retrieve the password:
selectCommand.CommandText = "SELECT password FROM cpr_users.cpr_user_info WHERE username=#User";
var myReader = selectCommand.ExecuteReader();
if(myReader.Read())
{
var stored = myReader["password"].ToString();
//do the rest of comparison here
}
The question is that a better approach is to ensure that you will NEVER have TWO or more users with the same "user id" in the database. If you ensure that (is the usual) you don't have to check how many users where returned with the "count".
Another point is that is best to send the passord and let the database (via stored proc) to check if the pass is the right one for the user.
Here i put some code... this code related to login system. here i have some problem.... when i enter right User id and Password or even Wrong User ID and Password both are authorized and display message Login successfully.......how can be this... i don't understand why SQLConnection give authorization to Unknown user which are not in database....
See the Code....
string SQlcons = "Data Source=(LocalDB)\v11.0;AttachDbFilename='|DataDirectory|Database1.mdf';Integrated Security=True"
private void button1_Click(object sender, EventArgs e)
{
String UN = txtUsername.Text;
String PW = txtPassword.Text;
string loginstr = "SELECT * FROM Login Where UserName = '" + UN + "' and Password = '" + PW + "'";
SQLconn = new SqlConnection(SQLcons);
SQLconn.Open();
try
{
SqlCommand cmd = new SqlCommand(loginstr, SQLconn);
cmd.ExecuteNonQuery();
MessageBox.Show("Welcome " + txtUsername.Text);
Records rcd = new Records();
this.Hide();
rcd.ShowDialog();
}
catch
{
MessageBox.Show("Enter Correct Password and ID :(");
txtUsername.Text = "";
txtPassword.Text = "";
}
SQLconn.Close();
}
Plz... Give the solution and Suggestion to me..
int result = cmd.ExecuteNonQuery();
if(result == 0)
{
//wrong login info,
} else {
MessageBox.Show("Login Success");
}
ExecuteScalar() function returns the row count with given SQL String. In your case, you should check the returned integer value from ExecuteScalar(). If result is 0, user entered wrong login info. If result is 1, user entered right information.