send verification code to email many times cause error message - c#

i use c# and asp.net , when the user create new account will enter email and national id as primary key then if user click (VIRIFY ME) button ,the program will store this info in sql server , and send email msg to the user , but my problem it when the user click on varify me button more than one it will print (email is already exist)
protected void Button1_Click2(object sender, EventArgs e)
{
LabelErrorMSG.Text = "";
String email = emailtextbox0.Text.Trim();
String notionalID = textbox_National_ID.Text.Trim();
try
{
if (notionalID != "" && email != "" && counter==1)
{
// insert notional ID and email into database
getdataobj.PageSignUpInsert(notionalID, email);
/////////////////////////////////////////////////////////////////////
conn.Open();
//Generate Verification Code
String code = getdataobj.GetRandomNumber().ToString();
// Set Verification Code in database
SqlCommand comm = new SqlCommand("UPDATE trained SET VerificationCode='" + code + "' where NationalID='" + notionalID + "'", conn);
comm.ExecuteNonQuery();
conn.Close();
//Send Email to the user with Verification Code
SmtpClient smtpClient = new SmtpClient();
MailMessage mailMessage = new MailMessage("saudiasummertraining#gmail.com", email, "", "");
mailMessage.To.Add(new MailAddress(email));
mailMessage.Subject = "Saudia Summer Traning";
mailMessage.Body = code;
smtpClient.EnableSsl = true;
smtpClient.Send(mailMessage);
Panel1.Visible = true;
}
else
{
LabelErrorMSG.Text = "you must insert national ID and email ";
}
////////////////////////////////////////////////////////////////////
}
catch (SqlException ex)
{
if (ex.Number == 2627)
{
if (ex.Message.Contains("UNIQUE"))
{
///error msg regarding Unique key violation.
LabelErrorMSG.Text = "The email already exist ";
}
if (ex.Message.Contains("PRIMARY"))
{
//error msg regarding Primary key violation.
LabelErrorMSG.Text = "The national ID already exist ";
}
}
}
}

When you want the user to can click the verification-button multible times, then you have to insert the Emai-Address only once because you set it to Unique.
You can check if the Email is already inserted, before you try to insert it. That should prevent this Error.

When the user will click on Verify me Button once conn.Open() will execute then the update process will continue and then conn.Close() will execute accordingly.
And When user will Click verify me button more than once conn.Open() will continue to execute multiple times and will update the process and wont execute
conn.Close() method, hence it will throw an exception.
Solution is Once user will click Verify me Button it should only be enabled again when user will verify email.

Related

Login Button to read sql database and confirm values entered into textboxes with values in said sql database throws error

I am a noob attempting to create a login page where the user enters their username and password that is already in the sqldatabase connected to the textboxes/button/form. The below code is my best attempt at doing so, but upon debugging it throws catch despite the textbox values entered being registered in the sql database. If any additional information is needed please ask.
private bool compareStoD(string teststring1, string teststring2)
{
return String.Compare(teststring1, teststring2, true, System.Globalization.CultureInfo.InvariantCulture) == 0 ? true : false;
}
private void button1_Click_1(object sender, EventArgs e)
{
try
{
SqlConnection connection = new SqlConnection(#"Data Source=DESKTOP-P3JSE1C;Initial Catalog=logins;Integrated Security=True");
connection.Open();
SqlCommand checker = new SqlCommand("SELECT COUNT (*) from users WHERE username='" + textBox1.Text + "'AND pssword='" + textBox3.Text + "'", connection);
SqlDataReader reader = checker.ExecuteReader();
string usernameText = textBox1.Text;
string psswordText = textBox3.Text;
while (reader.Read())
{
if (this.compareStoD(reader["username"].ToString(), textBox1.Text) && // replace textbox1.Text with text string usernameText
this.compareStoD(reader["pssword"].ToString(), textBox3.Text)) //replace textbox3.Text with text string psswordText
{
main wen = new main();
wen.Show();
}
}
reader.Close();
connection.Close();
}
catch
{
MessageBox.Show("Incorrect password or username.");
}
}
It is most likely throwing an exception because your query is asking for the count but then you are reading columns username and password which do not exist in the reader. This is your query:
SELECT COUNT (*)
Change that to this:
SELECT username, password ...
Also, unless you want every savvy user to access your application, use SqlParameter to avoid SQL Injection
Another Suggestion
I am not sure what main is, my assumption it is some window, but I would not show it where you are showing right now. Try to close the reader as soon as possible and then show the window if the user is authenticated like this.
bool userIsAuthenticated = false;
if (reader.Read())
{
// if a row was returned, it must be the row for the user you queried
userIsAuthenticated = true;
}
reader.Close();
connection.Close();
// Now that the reader is closed, you can show the window so the reader does not stay
// open during the duration of the main window
if (userIsAuthenticated)
{
main wen = new main();
wen.Show();
}
Select count returns the count not the row, if you want the row itself change to select username, password instead of select count(*) . See this link
There is over work being done by your code. You are querying the database by comparing the username and password values from UI to the values in the table. And once and if values are retrieved from the database you are again comparing value from UI to the values coming from the database. This is unnecessary.
The query will return the values only if values match in the database so you don't need to compare them again. So method compareStoD is not required at all.
The button1_Click can be changed as following to make it simpler.
private void button1_Click_1(object sender, EventArgs e)
{
try
{
SqlConnection connection = new SqlConnection(#"Data Source=DESKTOP-P3JSE1C;Initial Catalog=logins;Integrated Security=True");
connection.Open();
SqlCommand checker = new SqlCommand("SELECT COUNT (*) from users WHERE username=#userName AND pssword = #password", connection);
checker.Parameters.Add(new SqlParameter("#userName", textBox1.Text));
checker.Parameters.Add(new SqlParameter("#password", textBox3.Text));
var count = Convert.ToInt32(checker.ExecuteScalar());
connection.Close();
if(count > 0)
{
main wen = new main();
wen.Show();
}
else
{
MessageBox.Show("Incorrect password or username.");
}
}
catch
{
MessageBox.Show("Incorrect password or username.");
}
}
Also one good practice while supplying values from Textbox, you should use Textbox.Text.Trim() which helps in eliminating the spaces at the beginning and end. These spaces can create a problem in later stage.

C# - MySQL Database, Check password is correct when it's encrypted?

I'm using a MySQL database with my program and when I check if the password a user enters is correct, it always says it's invalid. I do the same with email but it works. I think it's because my PHP script encrypts the password when it's created on the page. Here is my code:
try
{
string command = "SELECT email FROM uc_users WHERE email = '#email';";
string command2 = "SELECT password FROM uc_users WHERE password = '#password';";
// CONNECTION DETAILS
connection = new MySqlConnection(connectionString);
connection.Open();
// COMMAND DETAILS
MySqlCommand email = new MySqlCommand(command, connection);
MySqlCommand passwordc = new MySqlCommand(command2, connection);
// PARAMETERS
email.Parameters.AddWithValue("#email", txtEmail.Text);
passwordc.Parameters.AddWithValue("#password", txtPassword.Text);
// READER DETAILS
MySqlDataReader dr;
MySqlDataReader dr2;
// CHECK DETAILS
dr = email.ExecuteReader();
string tempE = dr.Read() ? dr.GetString(0) : "Invalid Email";
dr.Close();
dr2 = passwordc.ExecuteReader();
string tempP = dr2.Read() ? dr.GetString(0) : "Invalid Password";
dr2.Close();
MessageBox.Show(tempE + " " + tempP);
if (tempE == txtEmail.Text && tempP == txtPassword.Text)
{
connection.Close();
tempE = "";
tempP = "";
string email2 = txtEmail.Text;
frmAppHub frm = new frmAppHub(email2);
frm.Show();
this.Hide();
}
else
{
MessageBox.Show("Invalid login details. Please try again.");
connection.Close();
tempE = "";
tempP = "";
}
}
catch(MySqlException ex)
{
MessageBox.Show("MySQL Error - Code AHx004: " +ex.Message);
connection.Close();
}
Any ideas how to do it? Any help is appreciated.
The query is fundamentally broken. There should be one query and the approach should be like:
// No quotes around placeholder and only ONE query that does NOT select on the password.
// If the query selects on the password then it means that the password is either
// stored as plaitext (which is not good) or the database value can be computed without
// per-user information (which is also not good).
string command = "SELECT email, password FROM uc_users WHERE email = #email";
// Only look based on the user (the email column should have a Unique constraint)
// as (although a unique salt makes it very unlikely) passwords are not unique
// nor do they identify users.
email.Parameters.AddWithValue("#email", txtEmail.Text);
// Then read the password for the given user
dr = email.ExecuteReader();
if (!dr.Read()) {
// User not found - just stop.
return false;
}
string dbPassword = dr.GetString(1);
return IsPasswordMatch(dbPassword, txtPassword.Text);
Now, IsPasswordMatch is a function which, when, given the database password and the plain-text password, should determine if they are a match by applying all the appropriate hash/salt/whatever transforms (see my first comment). In any case, all the logic can be safely tucked away in there.
It might look something like:
bool IsPasswordMatch (string dbPassword, string plaintext) {
var salt = GetSalt(dbPassword);
var dbHash = GetHash(dbPassword);
var ptHash = Hash(salt + plaintext);
return dbHash == ptHash;
}
I've left in the methods as "high level operations" that need to be adapted to whatever was used in the first place; however, the basic operation should now be apparent. Just repeat the same process as was used to create the database value in the first place - is it the same in both cases?
Make sure to read up on using as well - this will enable resources to be cleaned up easily without fuss.
Yes, you need to generate hash of your password, that must be identical stored in database and than query your command with this hash, instead of plain text password.
If you have different strings in DB and #passowrd - you always have invalid result.

username duplication validation

I'm making a simple log-in page for out thesis and I'm already done with the character length and password mismatch validation.. my problem is how do I test if the given username already exist in my database.... I'm coding in C# and making use of SQL management studio R2 for my database....
private void add_Click(object sender, EventArgs e)
{
string UserName = textBox1.Text;
string Password = maskedTextBox1.Text;
if (Password.Length <= MiN_LENGHT && UserName.Length <= MiN_LENGHT)
{
errorProvider1.SetError(textBox1, "User name must be at least 8 character");
errorProvider2.SetError(maskedTextBox1, #"Password must be at least 8 character");
maskedTextBox1.Clear();
maskedTextBox2.Clear();
}
else if (maskedTextBox1.Text != maskedTextBox2.Text)
{
errorProvider1.SetError(maskedTextBox2, "Passwords don't match");
maskedTextBox1.Clear();
maskedTextBox2.Clear();
}
else if (textBox1.Text == "" || maskedTextBox1.Text == "" ||
maskedTextBox2.Text == "")
{
MessageBox.Show("Please fill up the required records", "Information",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
x.da.InsertCommand = new SqlCommand(#"Insert into PlayerList
VALUES(#uname,#pw,#repw)", x.cs);
x.da.InsertCommand.Parameters.Add("#uname", SqlDbType.NVarChar).Value =
textBox1.Text;
x.da.InsertCommand.Parameters.Add("#pw", SqlDbType.NVarChar).Value =
maskedTextBox1.Text;
x.da.InsertCommand.Parameters.Add("#repw", SqlDbType.NVarChar).Value =
maskedTextBox2.Text;
x.cs.Open();
x.da.InsertCommand.ExecuteNonQuery();
MessageBox.Show("Record Added", "Information", MessageBoxButtons.OK,
MessageBoxIcon.Information);
button3.Enabled = true;
x.da.SelectCommand = new SqlCommand( #"Select PlayerCode, uname from
PlayerList", x.cs);
x.ds.Clear();
x.da.Fill(x.ds);
dataGridView1.DataSource = x.ds.Tables[0];
x.cs.Close();
}
}
hope you can help....
You can add a UNIQUE CONSTRAINT or INDEX on the username field in the database and catch the exception, or you can search for it beforehand. I recommend the first alternative, as it avoids a race condition, but that shouldn't preclude you from doing the search as well.
Before you store the new user, you first do a check if that username already exists in the database, if the user does not exist then you save that record.
if that username does exist you skip saving it, and show a friendly message to the user that his or her username is already in use
Are you sure you want to do the validation in log-in page? I think this validation done is sign-up page.
You can do this validation in two ways
1--> Do an ajax call after user enters username and show the duplicate message if username already exists.(Mean while user will be providing password so user time will be saved).
2--> In the 2nd approach you can do the validation completely in server side. Get the username and compare it with existing user names and show the message accordingly.
on textchanged event of username textbox you just query from databse that
select username from user_mst where username='"+textusernm.text+"';
if it is there then jst display error message and disable save button
& if not jst enable save button and save it

How to force user to enter value in a database field

With my Application, i want to make sure if user enter no value in a textbox, and click on the
save button to send data in the sqlserver db.The database side validation prevent this violation and set ErrorMessage which my application will catch and Display a meaninful Message
to the User. For each required field i set it to NOT NULL. But when i test,i can still enter
enter empty textbox values it gets inserted with out value.
what am i missing?
string connectionstring = "Data Source=abcdef;Initial Catalog=HMS;Persist Security Info=True;User ID=sysad;Password=abcdef";
SqlConnection connection = new SqlConnection(connectionstring);
string SelectStatement = "SELECT * FROM tablename where RegistrationNo = #RegistrationNo";
SqlCommand insertcommand = new SqlCommand(SelectStatement, connection);
insertcommand.Parameters.AddWithValue("#RegistrationNo", textBox10.Text);
SqlDataReader reader;
try
{
connection.Open();
reader = insertcommand.ExecuteReader();
while (reader.Read())
{
textBox11.Text = reader["RegistrationNo"].ToString();
textBox1.Text = reader["Appearance"].ToString();
textBox2.Text = reader["VolumePH"].ToString();
textBox3.Text = reader["Mobility"].ToString();
textBox4.Text = reader["Viability"].ToString();
textBox5.Text = reader["Head"].ToString();
textBox6.Text = reader["MiddlePiece"].ToString();
textBox7.Text = reader["Tail"].ToString();
textBox8.Text = reader["SpermCount"].ToString();
dateTimePicker1.Text = reader["Date"].ToString();
textBox9.Text = reader["Comment"].ToString();
}//end while
reader.Close();
}
catch (Exception ex)
{
throw ex;
}//end catch
What am i missing?
I think you are missing a distinction between null and an empty string.
Databases distinguish between null and empty. If your ToString succeeds, then you have a non-null string there, and so DB is happy to accept it as a valid value.
In general, using DB for user-side validation is somewhat wasteful: if you know that the field must not be empty, you should check for it in the UI; DB validation should serve as the last resort that preserves the integrity of your data model.
You can use requiredfield validator in the Server side code and validate. If it is empty string return error there itself.
Going to sql server and throwing error is bad.
if(txtBox.Text.Trim() == string.Empty)
//throw "cannot be null error to user;
Its better to check the user input in the user interface. If the user have to enter some value you should check it before trying to insert it to the database.
May be a good idea is to check the fields when you press the button. Example:
private void button_Click(object sender, EventArg e){
if (textbox1.Text == ""){
MessageBox.Show("Your message to the user");
}
}
Hope it helps

how to add a database field in the c# code without using stored procedures in a disconnected architecture

I need to create login page in asp.net where i have to create 3 user access levels such as
users who can view there email and updates
superusers who can view there email, updates and also delete some users
admin who can view all and delete superusers as well.
my login page has
username
password and login button
when the user/admin/superuser clicks on the button it should automatically redirect him depending on the user levels.
i have a database of username, password, userid, useraccesstype, email.
my problem here is i am not getting how to write the if commands basing on the useraccesstype in a disconnected architecture of database and also without using stored procedures.
String Uid = TextBox1.Text;
String Pwd = TextBox2.Text;
SqlConnection con = new SqlConnection(#"Data Source=Sun-PC\SQLEXPRESS;Initial Catalog=dts;Persist Security Info=True;User ID=sa;Password=********;");
SqlDataAdapter da;
da = new SqlDataAdapter("Select userid,password,useraccesstype from Table2 WHERE userid = " + Uid + " and password ='" + Pwd + "'", con);
DataSet ds = new DataSet("Table2");
da.Fill(ds, "Table2");
if (Uid == "userid" && Pwd == "password")
{
if (uzrtype3 = "componentadmin")
{
Response.Redirect("userpage.aspx");
}
if (uzrtype = "user")
{
Response.Redirect("register.aspx");
}
}
else
{
Label123.Text = "Sorry, user not recognized - please try again";
}
Reading between the lines, I think you are asking "how t get the useraccesstype"? If so with the current code, maybe:
if(ds.Tables[0].Rows.Count == 1) {
// match
var accessType = ({appropriate cast here})ds.Tables[0].Rows[0]["useraccesstype"];
} else {
// no match
}
However! I would do it a different way, solving the various parameter issues and making it much safer - using "dapper-dot-net" for convenience (google it):
string userid = ....
string password = ...
var row = con.Query(
"Select useraccesstype from Table2 WHERE userid = #userid and password = #password",
new { userid, password }).FirstOrDefault();
if(row == null) {
// no match
} else {
var accessType = ({some cast here})row.useraccesstype;
}
The salted hashing of passwords is also something you should look into.
No point returning the userid/password : you already know those. You could also use ExecuteScalar, but then you need to handle the parameters yourself.

Categories

Resources