Hi there, Im having some trouble implementing a secure login facility to a website im creating. I have managed to be able to register new members onto the database with hash values.
However i cannot seem to logon using the same credentials. I believe it's a problem with the SQL reader not reading the table correctly. I did origianlly have a SQL Stored Procedure setup.
Code Below (Login.aspx.cs);
Code:using System; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; using System.Security.Cryptography; using System.Data.SqlClient; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } private static string CreateSalt(int size) { // Generate a cryptographic random number using the cryptographic // service provider RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); byte[] buff = new byte[size]; rng.GetBytes(buff); // Return a Base64 string representation of the random number return Convert.ToBase64String(buff); } private static string CreatePasswordHash(string pwd, string salt) { string saltAndPwd = String.Concat(pwd, salt); string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile( saltAndPwd, "SHA1"); hashedPwd = String.Concat(hashedPwd, salt); return hashedPwd; } protected void btnRegister_Click(object sender, EventArgs e) { int saltSize = 5; string salt = CreateSalt(saltSize); string passwordHash = CreatePasswordHash(txtPassword.Text, salt); try { StoreAccountDetails(txtUserName.Text, passwordHash); } catch (Exception ex) { lblMessage.Text = ex.Message; } } private void StoreAccountDetails(string userName, string passwordHash) { // See "How To Use DPAPI (Machine Store) from ASP.NET" for information // about securely storing connection strings. ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["ConnectionString"]; SqlConnection conn = new SqlConnection(settings.ConnectionString); SqlCommand cmd = new SqlCommand("RegisterUser",conn); cmd.CommandType = CommandType.StoredProcedure; SqlParameter sqlParam = null; //Usage of Sql parameters also helps avoid SQL Injection attacks. sqlParam = cmd.Parameters.Add("@userName", SqlDbType.VarChar, 20); sqlParam.Value = userName; sqlParam = cmd.Parameters.Add("@passwordHash ", SqlDbType.VarChar, 40); sqlParam.Value = passwordHash; try { conn.Open(); cmd.ExecuteNonQuery(); } catch( Exception ex ) { // Code to check for primary key violation (duplicate account name) // or other database errors omitted for clarity throw new Exception("Exception adding account. " + ex.Message); } finally { conn.Close(); } } private bool VerifyPassword(string suppliedUserName, string suppliedPassword) { bool passwordMatch = false; // Get the salt and pwd from the database based on the user name. // See "How To: Use DPAPI (Machine Store) from ASP.NET," "How To: // Use DPAPI (User Store) from Enterprise Services," and "How To: // Create a DPAPI Library" for more information about how to use // DPAPI to securely store connection strings. ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["ConnectionString"]; SqlConnection conn = new SqlConnection(settings.ConnectionString); SqlCommand cmd = new SqlCommand("SELECT PasswordHash FROM Users WHERE UserName = @userName", conn); //Usage of Sql parameters also helps avoid SQL Injection attacks. cmd.Parameters.Add("@userName", SqlDbType.VarChar, 20); cmd.Parameters["@userName"].Value = suppliedUserName; try { conn.Open(); SqlDataReader reader = cmd.ExecuteReader(); reader.Read(); // Advance to the one and only row // Return output parameters from returned data stream string dbPasswordHash = reader.GetString(0); int saltSize = 5; string salt = dbPasswordHash.Substring(dbPasswordHash.Length - saltSize); reader.Close(); // Now take the password supplied by the user // and generate the hash. string hashedPasswordAndSalt = CreatePasswordHash(suppliedPassword, salt); // Now verify them. passwordMatch = hashedPasswordAndSalt.Equals(dbPasswordHash); } catch (Exception ex) { throw new Exception("Execption verifying password. " + ex.Message); } finally { conn.Close(); } return passwordMatch; } protected void btnLogon_Click(object sender, EventArgs e) { bool passwordVerified = false; try { passwordVerified = VerifyPassword(txtUserName.Text, txtPassword.Text); } catch (Exception ex) { lblMessage.Text = ex.Message; return; } if (passwordVerified == true) { // The user is authenticated // At this point, an authentication ticket is normally created // This can subsequently be used to generate a GenericPrincipal // object for .NET authorization purposes // For details, see "How To: Use Forms authentication with // GenericPrincipal objects lblMessage.Text = "Logon successful: User is authenticated"; } else { lblMessage.Text = "Invalid username or password"; } } }



LinkBack URL
About LinkBacks


