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
Related
i'm creating a login page for my windows application in windows form app(.net framework) & C#, using visual studio 2019.
My login page has 2 text boxes for username and password, a login button and register button to switch to register form with some required field validations on each control.
I'm using SQL Server 2014 and have 3 tables in there, Student, Admin, and Coordinator, each one has columns for their details such as UserId, Username, Password, Email, Age, Gender, Address, Contact.
What i would like to do is when the user presses the submit button, it checks the student table for the username and its password, if its not there, it checks the Coordinator, then the admins. If its not in any of them, it gives an error that the login failed.
I put an SQLCommand on the page that pulls the username and password from the student table where they are equal to the textboxes text.
Do i need to add 3 sqlcommands to page for each table? Or need to create 3 login form for each user?
My code works but its only check Admin table, not Coordinator and Student tables
Is there a better way to do it??
private void btnLogin_Click(object sender, EventArgs e)
{
try
{
bool valid = true;
if (string.IsNullOrEmpty(uName.Text) || string.IsNullOrEmpty(password.Text))
{
MessageBox.Show("Please! Enter Username and Password.", "Login Form", MessageBoxButtons.OK, MessageBoxIcon.Warning);
valid = false;
}
if (valid)
{
String UserType = null;
SqlCommand cmd = new SqlCommand("Select usertype from Admin where UserName = '" + uName.Text + "' and Password = '" + password.Text + "' ", con);
SqlDataReader dr = cmd.ExecuteReader();
Boolean records = dr.HasRows;
if (records)
{
while (dr.Read())
{
UserType = dr[0].ToString();
}
if (UserType.Equals("Admin"))
{
MessageBox.Show("Admin Just Logged In, Welcome!", "Login Form", MessageBoxButtons.OK, MessageBoxIcon.Information);
frmAdmin frmA = new frmAdmin();
frmA.Show();
this.Hide();
}
}
else
{
MessageBox.Show("Login Failed!", "User Login Form", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
dr.Close();
}
}
catch (Exception ex)
{
MessageBox.Show("Login Failed!" + ex);
}
}
I think you need 1 table instead of 3 you can call this table a Users table.
For roles like admin, user, the coordinator you can create another table like UserRoles.
(This will save you the need to create additional tables for each incoming roles)
So you can check one table if the user exists or not.
Please keep passwords hashed and have a read about SQL Injection.
Users Table
Id
UserTypeId
UserName
1
1
admin#noemail.com
1
2
coordinator#noemail.com
1
3
student#noemail.com
Users Roles
Id
UserRole
Description
1
admin
admin
2
coordinator
coordinator role
3
student
student role
4
teacher
teacher role
It's not the best way i know.
But right now the fastest way to solve your problem is using a combo box or some radio buttons and ask the user what is your role and use user selection.
This question already has answers here:
ASP.NET Identity 2.0 check if current user is in role IsInRole
(4 answers)
Unable to configure AspNet.Identity using PostgreSQL
(2 answers)
Closed 4 years ago.
I have a little web application on asp.net MVC + PostgreSQL.
I have login page, where people enters their login/password. Right now I only have 1 user - admin. If login and pass are correct, I enter to mainForm.aspx page.
But I need to make a couple of users: user and director. When user logs in, he needs to be redirected to user.aspx page, when director logs in, he needs to be redirected to director.aspx page. All cases need to make login/pass check from PostgreSQL database.
How do I do that?
Here's my Login.aspx.cs code with only 1 user:
namespace User1.WebApp
{
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;
}
protected void Button_Login_Click(object sender, EventArgs e)
{
var connString = "Host=localhost;Username=postgres;Password=123;Database=postgres";
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
string checkuser = "select count(*) from Login where name= '" + TextBoxUserName.Text + "' ";
NpgsqlCommand com = new NpgsqlCommand(checkuser, conn);
int temp = Convert.ToInt32(com.ExecuteScalar().ToString());
if (temp == 1)
{
string checkPasswordQuery = "select password from Login where name= '" + TextBoxUserName.Text + "'";
NpgsqlCommand passCom = new NpgsqlCommand(checkPasswordQuery, conn);
string password = passCom.ExecuteScalar().ToString().Replace(" ", "");
if (password == TextBoxPassword.Text)
{
Session["New"] = TextBoxUserName.Text;
Response.Redirect("MainForm.aspx");
}
else
{
Response.Write("Password is NOT correct !");
}
}
else
{
Response.Write("Username is NOT correct !");
}
}
}
}
}
You could do this just before
Response.Redirect("MainForm.aspx");
The way you can do it is to check the type of user and act accordingly.
Few comments regarding the current code:
Set the connection string in web.config and read it from there instead of having it hard coded in your code e.g. here.
The way you create your SQL statements makes your application vulnerable to SQL injection, one of the most common ways for someone to hack a site. Instead of doing this, prefer parameterized queries.
You make two round trips to the database, to check if the user exists and then to get her password. What about if you want to fetch one more information like the user type ? You would make one more round trip. You could eliminate all this to one round trip, provided that you can identify your users based on something unique like the username. Just fetch all the data for a specific username.
Let that someone can get access to the Login table of your database. How exposed are your application users ? 100%. All the passwords there are in clear text ! You should avoid this in any way. A naive solution is to hash the password and each time someone try to login to hash the password that the user provides and compare with the hash you have stored. A more professional approach of storing passwords is described at The right way to implement password hashing using PBKDF2 and C#. Look also for similar articles like the mentioned one. Security should be of paramount importance for your applications.
Are you able to store an extra field in the database to specify whether a login is Admin, User or Director?
You could use an Enum for this:
enum LoginRole
{
User = 0,
Director = 1,
Admin = 2
}
This Enum could be stored as an integer field in your Login table, called "role" or similar. You could then redirect to the appropriate page depending on this role.
I have updated your code with an example:
var connString = "Host=localhost;Username=postgres;Password=123;Database=postgres";
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
string checkuser = "select password, role from Login where name=#username";
using (var com = new NpgsqlCommand(checkuser, conn))
{
com.Parameters.AddWithValue("#username", TextBoxUserName.Text);
using (var reader = com.ExecuteReader())
{
if (reader.Read())
{
string password = reader["password"].ToString();
LoginRole role = (LoginRole)reader["role"];
if (password == TextBoxPassword.Text)
{
Session["New"] = TextBoxUserName.Text;
switch (role)
{
case LoginRole.User:
Response.Redirect("user.aspx");
break;
case LoginRole.Admin:
Response.Redirect("MainForm.aspx");
break;
case LoginRole.Director:
Response.Redirect("director.aspx");
break;
}
}
else
Response.Write("Password is NOT correct !");
}
else
Response.Write("Username is NOT correct !");
}
}
}
Please note, using parameters in your queries in this case would be preferred, as appending the string from the textbox straight into the SQL query is vulnerable to SQL injection.
You were also making two calls to the database per login - one to check the username and another to check the password. I have addressed this in my above sample to only make one call to the database.
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.
private void btnLogin_Click(object sender, EventArgs e)
{
{
Connections.con.Open();
string login = "SELECT ID, Username, [Password] FROM Employee";
OleDbCommand command = new OleDbCommand(login, Connections.con);
command.Connection = Connections.con;
command.Parameters.AddWithValue("#?", txtLUser.Text.ToString());
command.Parameters.AddWithValue("#?", txtLPass.Text.ToString());
OleDbDataReader reader = command.ExecuteReader();
int count = 0;
while (reader.Read())
{
count = count + 1;
break;
}
if (count == 1)
{
MessageBox.Show("Login Successful.");
this.Close();
}
else
{
MessageBox.Show("Please enter a valid Username or Password");
}
Connections.con.Dispose();
Connections.con.Close();
MessageBox.Show("Thank you for using this Simple Login/Registration Form.");
}
It always Logs in whenever i click Login Button and i haven't even typed anything in the user/pass textbox and there is no blank registered in my access database
any advice?
You're not actually checking the username and password. Look at the database query:
"SELECT ID, Username, [Password] FROM Employee"
This will select every record from the Employee table. Then you check those records:
while (reader.Read())
{
count = count + 1;
break;
}
if (count == 1)
{
MessageBox.Show("Login Successful.");
this.Close();
}
According to this logic, as long as any record exists in the Employee table, the login is successful.
You probably want to check only for records which match the supplied credentials. Something like this:
"SELECT [ID], [Username], [Password] FROM [Employee] WHERE [Username] = #? AND [Password] = #?"
(I'm guessing on the parameter syntax based on how you add the parameters, since I'm not familiar with MS Access syntax. But hopefully you get the idea.)
Also, and this is important, you appear to be storing user passwords in plain text. This is an extremely terrible thing to do. Please hash passwords appropriately so that they can't be read as plain text.
Additionally, you appear to be using a shared connection object:
Connections.con.Open();
This is going to cause a whole host of problems. It's a lot simpler and more stable to create the connection object within the scope of the method which uses it. Basically, a connection object should be created, used, and disposed in a very tight scope and should not leak outside of that scope.
You missed where attribute
string login = "SELECT ID, Username, [Password] FROM Employee where Username=#? and [Password]= #? ";
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