In this situation, there is a form used for updating user information (username, password, mobile number, etc.).
Below is the code I used to check if the username exists in the database:
string sql = "SELECT username FROM (SELECT username FROM useraccount WHERE username != #old_uname)ua WHERE BINARY username = #new_uname LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(sql, SecurityMod.dbconn());
cmd.Parameters.AddWithValue("#old_uname", old_uname);
cmd.Parameters.AddWithValue("#new_uname", new_uname);
if (cmd.ExecuteScalar() == null)
{
isValidNewUname = true;
}
It works if the user really changes his/her username. But the problem occurs when the user made changes to anything but the username field. The isValidNewUname variable remains false. Any ideas and suggestions would be a big help.
Instead of basing on fetched username, I opted instead for the uid. I solved the problem with the following code:
string sql = "SELECT uid FROM useraccount WHERE BINARY username = #new_uname;";
MySqlCommand cmd = new MySqlCommand(sql, SecurityMod.dbconn());
cmd.Parameters.AddWithValue("#new_uname", new_uname);
if (cmd.ExecuteScalar() == null || cmd.ExecuteScalar().ToString() == userID)
{
isValidNewUname = true;
}
This code is shorter and more simple hence easier to maintain. What happens here is that the query looks for the uid of the #new_uname in the database. It then compares the fetched uid to the uid of the current user. If it is the same, it means that the fetched result of the query is simply the user itself, so it doesn't really matter if their the same or not since it belongs to only one user. If the fetched uid is not equal to the uid of the current user, it means the username input by the user is already taken so isValidNewUname would be false. If the query above doesn't return results, then the #new_uname is available since it doesn't have a record in the database.
Related
Would someone be kind enough to give a "green horn" a hand with this? Currently working on this project. Now the idea here is to retrieve the password from database, and match it with what the user types in. The stored password is encrypted using Bcrypt. I've tried different ways now but I still cannot get the passwords to match.
Here's part of the code.
// String command used from SQL, match AccountNo with Accountbox, Password with Passwordbox, from the Accounts dbo.
string a = string.Format("Select * from Accounts where AccountNo='{0}' and Password='{1}'", Accountbox ,Passwordbox);
SqlCommand ACCcheck = new SqlCommand(a, conn);
conn.Open();
SqlDataAdapter adapt1 = new SqlDataAdapter(ACCcheck);
DataSet data1 = new DataSet();
adapt1.Fill(data1);
SqlDataReader read = ACCcheck.ExecuteReader();
try
{
if (read.Read())
{
string salt = BCryptHelper.GenerateSalt(10);
string hash = BCryptHelper.HashPassword(Passwordbox, salt);
string OGpassword = read["Password"].ToString();
string givenPass = BCryptHelper.HashPassword(hash, Passwordbox);
if (givenPass.Equals(OGpassword))
{
//if (read.HasRows) // if input data valid, then proceed. if not then close conn and force retry.
//{
MessageBox.Show("WORDKING!");
conn.Close();
read.Close();
string q = string.Format("Select * from Transactions where AccountNo =" + Accountbox); // Fetch data from transaction table
SqlCommand cmd = new SqlCommand(q, conn); // SQL query, checks if what the user has written is a match with whats on the Db. Accountbox and Passwordbox are Inputbox I've used for this program.
I don't know if I have a SQL error here or if it's the Bcrypt part that's broken.
Thanks in advance for the aid.
thats not how you match the password from database if you use bcrypt e.g if i use same string to get hash it will return different hash even if string is same
string str = "asdf";
string pass = BCrypt.Net.BCrypt.HashPassword(str, 10);
string pass2 = BCrypt.Net.BCrypt.HashPassword(str, 10);
bool a = pass == pass2;
a will always be false because bcrypt doesn't work like that instead to verify password you have to use its own method Verify
BCrypt.Net.BCrypt.Verify(str, pass);
now it will return true here str is the password string you will get from the txtbox and pass is the hashed password stored in the database.
When you encrypt the password for the first time, you need to store the Salt along with the encrypted password in your table.
When you decrypt the password, you should use the same salt that was used for encrypting.
If you save the salt in your table, then you should remove the and Password='{1}' condition from your select statement too and check the password after retrieving the user account record.
What I am trying to do is grab the current logged in users username and compare that against a database which contains users, and also includes an Active flag and an Admin flag. I want to compare the current logged in user in the tbl_Person table and their respective user in the table to see if they are marked as Active and Admin. If both are true, they get access to an Admin page. I have the below so far which isn't working. Some of which I know why, some I don't. I think I am on the right track, that being said I am sure I am not doing it correctly. I know you use ExecuteScalar() to return something along with OUTPUT in the query string but couldn't get that to work. The other glaring issue is that I am trying to return integers when the username is a string and the active and admin flags are Bools. I know that I only have Active in there are the moment. I was trying to get that to work before adding in something else.
I read that with the ExecuteScalar, you could Parse and convert ToString, but that didn't work and I found evidence that this might not be the correct thing to do, but I'm really not sure.
I have got a few different errors. Type errors, invalid column when I've tried to do the OUTPUT. With OUTPUT I tried as just OUTPUT and because I know when returning after inserting, you do inserted.name. I tried selected.name as a hunch, but that didn't work.
I was thinking that if I pulled the info, concatenated them and then did a comparison, that this would do what I want, but I am open to other suggestions. Thanks.
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HSEProjRegConnectionString1"].ConnectionString);
conn.Open();
SqlCommand sqlUserName = new SqlCommand("SELECT [username] FROM [tbl_Person]", conn);
SqlCommand sqlActive = new SqlCommand("SELECT [active] FROM [tbl_Person]", conn);
int result1 = ((int)sqlUserName.ExecuteScalar());
int result2 = ((int)sqlActive.ExecuteScalar());
string userInfo = result1 + "." +result2;
string userName = userName + "." +result2;
if (userInfo == userName)
{
Woo, you have access.
}
else
{
Sorry, but no.
}
The Query isn't final either. Once it is working, I'll change it to a parameterised query.
Okay, consider the following code:
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HSEProjRegConnectionString1"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT [active] FROM [tbl_Person] WHERE username = #username", conn))
{
// since we can literally filter the results, if something comes back
// we know they are registered
cmd.Parameters.AddWithValue("#username", userName);
var res = cmd.ExecuteScalar();
bool registeredAndActive = (bool)res;
// unless of course `[active]` is an INT -then do this
bool registeredAndActive = (int)res == 1 ? true : false;
// but really -set [active] up as a BIT if it's not **and**
// please make it non-nullable :D
}
}
I'm pretty sure it does what you want. But it also shows you some best practices like:
Leverage the using statement for all IDisposable objects.
Filter the query as much as you can and make only one round trip.
i would like to be able to get the ID of the Current user logged in on my Site.
The thing is that i'm not trying to get the Guid, but The User_ID, that is a field that i have on a custom table of mine called Users. On that table i have User_ID that is the PK and UserId that is a FK from the table aspnet_Users.
The reason i want this field is because i have a table Purchase that every time an User LOGGED IN presses the button saying (Buy), a new saleId is incremented and the User_ID that bought it. On my table Users the User_ID is of int type that starts at 1 and also increments every time a newUser registers on the site.
So it's easier to check an user by ID of (1,2,3) that an unique Identifier with 30 characters
What i have in mind is something like this:
protected void Button1_Click(object sender, EventArgs e)
{
string InsertSql = "INSERT INTO [Purchase] (User_ID) VALUES (#User_ID)";
using (Connection)
{
Connection.Open();
SqlCommand com = new SqlCommand(InsertSql, Connection);
com.Paramaters.AddWithValue("#User_ID", ????);
com.ExecuteNonQuery();
cn.Close();
}
}
Where is ???? i need to get somehow the User_ID of the current User logged in that is on my custom table Users.
Thanks for the help
After Log-in into your application you should maintain the userid into session variable ..so that later on you can use that directly.
Example:-
//while user logged-in,push userid into session variable:-
Session["userid"] = 12;
//And later on in oyur page you can use it like :-
com.Paramaters.AddWithValue("#User_ID", (int)Session["userid"]);
Assuming as you say that using is logged in
Use User.Identity.Name.
You check if user is authenticated using:
User.Identity.IsAuthenticated
If will give you the name of the current logged user in your asp.net application.
com.Paramaters.AddWithValue("#User_ID", User.Identity.Name);
If I understood right, you have a custom table Users, with PK User_ID and a column UserId that is a FK to the table aspnet_Users.
You already know the UserName of the logged in user, so why not simply do something like:
string InsertSql = #"
INSERT INTO [Purchase] (User_ID)
SELECT U.User_ID FROM Users U
INNER JOIN aspnet_Users AU ON U.UserId = AU.UserId
WHERE AU.LoweredUserName = LCASE(#UserName)
";
Your #UserName parameter is then the name of the current logged on user that you already know (HttpContext.Current.User.Name), and you don't need to know the User_ID.
If you are using Membership then
Gets the name if authenticated.
if (User.Identity.IsAuthenticated)
Label1.Text = HttpContext.Current.User.Identity.Name;
else
Label1.Text = "No user identity available.";
If you want to get userid then run a select query like
Select userid from tablename where username = 'pass here username';
by running this query you will get userid and use that userid when you need.
Parametrized Query:
com.Paramaters.AddWithValue("#User_ID", HttpContext.Current.User.Identity.Name);
and if you are not using Membership then at the time of login get userid from your username and use any where you want to.
Note: Make sure that you have unique username otherwise it will give you multiple userid.
Logic 2:
Use the ProviderUserKey member of the MembershipUser object, like this:
MembershipUser user = Membership.GetUser();
string userid = user.ProviderUserKey.ToString();
Hope it works..
i finally did it, i kinda moved on to other stuff that i needed to do on my Site, so i just figured it out today.
I just wanna say thanks for all the replies and leave the solution to my own problem. Basically what i was doing wrong was the Select command. I'm not very good at SQL, so i didn't know were to place it xD, but now i know.
protected void Button1_Click(object sender, EventArgs e)
{
MembershipUser usr = Membership.GetUser(HttpContext.Current.User.Identity.Name);
Guid usrid = (Guid)usr.ProviderUserKey;
String product= DropDownList1.SelectedValue.ToString();
string InsertSql= "INSERT INTO [Purchase] (Product_ID, User_ID) VALUES (#Product_ID,(SELECT User_ID from [Users] where UserId = #UserId))";
using (Connection)
{
Connection.Open();
SqlCommand com = new SqlCommand(InsertSql, Connection);
com.Parameters.AddWithValue("#Product_ID", product);
com.Parameters.AddWithValue("#UserId", usrid);
com.ExecuteNonQuery();
Connection.Close();
}
Response.Redirect("Purchase.aspx");
}
Once again, thanks for all the patience and help
Take Care
When 'login' button is clicked I would like to iterate through a column in a table and check if a match occurs. How would I go about doing this?
I have connected through to a database and I'm reading from database and writing to database fine. I am not sure how I would iterate through a database.
P.S I'm new to both c# and visual studios. I am not having much trouble with C#, since I come over from Java however I'm struggling to get into grips with Visual studios.
This is simple you'll see.
SqlConnection myConnection = new SqlConnection(#"Server = (Local); Integrated Security = True;" + "Database = insertDataBaseName"); // Assuming (Local)
myConnection.Open();
SqlCommand myCommand = myConnection.CreateCommand();
myCommand.CommandText = ("SELECT UserName, Password,from Login"); // Where Login is your table . UserName and Password Columns
SqlDataReader myReader = myCommand.ExecuteReader();
bool login = false;
while (myReader.Read())
{
if (userNameBox.Text.CompareTo(myReader["UserName"].ToString()) == 0 && passwordBox.Text.CompareTo(myReader["Password"].ToString()) == 0) // A little messy but does the job to compare your infos assuming your using a textbox for username and password
{
login = true;
}
}
if (login)
{
//Your're in.
}
else
{
MessageBox.Show("Invalid UserName or Password", "Access Denied"); // Error message
}
myReader.Close();
myConnection.Close(); // Just close everything
Hope this helps.
Dont hesitate if you have any question on this code part.
in sql something like this will help
Select top(1) from Users where Id = #Id
or in linq
var user = (from u in users
where u.Id == id
select u).SingleOrDefault();
If you are chekcing for a username password validation, I think you should not get all user records and loop Iterate thru that. What if you get 100000 user registrations ? You really want to iterate 100000 times ? Really ?
You should probably query for the purticular record you are looking for
Some thing like this
SELECT TOP 1 UserID,FIRSTNAME,LASTNAME,HASHED_PASSWORD,SALT WHERE USERNAME='kristy'
Execute that query againinst your database and see whether you have any records exist, If you have one record present, now you can validate the password with the data you have.
I am so close to get this project done. I need to retrieve the password and passwordSalt from my Membership table to compare it to my 'OldPasswords' table.
The problem is the Membership provider does not let me use the GetPassword method because the password is hashed.
And I can not retrieve it in a normal sqlConnection because the UserID is hashed also.
Does anyone know how to hash the UserID so I can put it in my where clause?
Or maybe there is a different way to get to that data?
Any help is appreciated.
Thank you,
Steve
Steve, the UserId is not hashed. You may be confusing UserName with UserId (ProviderUserKey) which is a Guid.
In the context of your other questions: You should reference this code in both the code that you use to create a new user in order to log the initial password hash, salt and format AND in the OnPasswordChanging so that you can check/reject/insert.
This will get the relevant information for the currently logged in user:
var user = Membership.GetUser();
var userId = user.ProviderUserKey;
MembershipPasswordFormat passwordFormat;
string passwordSalt;
string password;
var cstring = WebConfigurationManager.ConnectionStrings["localSqlServer"];
using (var conn = new SqlConnection(cstring.ConnectionString))
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "select PasswordFormat,PasswordSalt,Password from aspnet_Membership where UserId=#UserId";
cmd.Parameters.AddWithValue("#UserId", userId);
conn.Open();
using (var rdr = cmd.ExecuteReader())
{
if (rdr != null && rdr.Read())
{
passwordFormat = (MembershipPasswordFormat) rdr.GetInt32(0);
passwordSalt = rdr.GetString(1);
password = rdr.GetString(2);
}
else
{
throw new Exception("An unhandled exception of type 'DoesntWorkException' has occured");
}
}
}
}
//do something interesting hew with passwordFormat, passwordSalt , password
There seem to be a couple of different things going on here...
You cannot recover a hashed password. Period. The purpose of hashing is to prevent exactly this kind of recovery.
You can hash the User ID for a lookup if the User ID value is already hashed in the database for some reason (although, that is a little strange, there is no good reason to hash a User ID). But you need to know how it was hashed. If it's MD5 or SHA1, the quickest way is to use FormsAuthentication.HashPasswordForStoringInConfigFile (but use it on the user name instead of the password).
The salt should definitely not be hashed, otherwise it's unusable. Salts are appended to the clear-text password before hashing, so whatever value you see in the salt column is the salt.