Step 5. Use ADO.NET to Store Account Details in the Database
This procedure modifies the Web application code to store the supplied user name,
generated password hash and salt value in the database.
To use ADO.NET to store account details in the database
-
Return to Visual Studio .NET and double-click the Register button on the
Web form to create a button click event handler.
-
Add the following code to the method.
3.
int saltSize = 5;
4.
string salt = CreateSalt(saltSize);
5.
string passwordHash = CreatePasswordHash(txtPassword.Text,salt);
6.
try
7.
{
8.
StoreAccountDetails( txtUserName.Text,
passwordHash);
9.
}
10.catch(Exception ex)
11.{
12.
lblMessage.Text = ex.Message;
13.}
-
Add the following using statement at the top of the file, beneath the existing
using statements.
15.using System.Data.SqlClient;
-
Add the StoreAccountDetails utility method using the following code. This
code uses ADO.NET to connect to the UserAccounts database and stores the
supplied username, password hash and salt value in the Users table.
17.private void StoreAccountDetails( string
userName,
18.
string
passwordHash )
19.{
20.
// See "How To Use DPAPI (Machine Store) from ASP.NET" for
21.
information
22.
// about securely storing connection strings.
23.
SqlConnection conn = new SqlConnection( "Server=(local);" +
24.
"Integrated
25.
Security=SSPI;"
+
26.
"database=UserAccounts");
27.
28.
SqlCommand cmd = new SqlCommand("RegisterUser", conn );
29.
cmd.CommandType = CommandType.StoredProcedure;
30.
SqlParameter sqlParam = null;
31.
//Usage of Sql parameters also helps avoid SQL Injection attacks.
32.
sqlParam = cmd.Parameters.Add("@userName", SqlDbType.VarChar,
33.
20);
34.
sqlParam.Value = userName;
35.
36.
sqlParam = cmd.Parameters.Add("@passwordHash ", SqlDbType.VarChar,
37.
40);
38.
sqlParam.Value = passwordHash;
39.
40.
try
41.
{
42.
conn.Open();
43.
cmd.ExecuteNonQuery();
44.
}
45.
catch( Exception ex )
46.
{
47.
// Code to check for primary key violation (duplicate account
48.
name)
49.
// or other database errors omitted for clarity
50.
throw new Exception("Exception adding account. " + ex.Message);
51.
}
52.
finally
53.
{
54.
conn.Close();
55.
}
56.}
Step 6. Authenticate User Credentials Against the Database
This procedure develops ADO.NET code to look up the supplied user name in the database
and validate the supplied password, by matching password hashes.
Note In many Forms authentication
scenarios where you are using .NET role-based authorization, you may also retrieve
the roles that the user belongs to from the database at this point. These can subsequently
be used to generate a GenericPrincipal object that can be associated with
authenticated Web requests, for .NET authorization purposes.
For more information about constructing a Forms authentication ticket incorporating
a user's role details, see "How To: Create GenericPrincipal Objects with Forms Authentication
in ASP.NET 1.1" in the Reference section of this guide.
To authenticate user credentials against the database
-
Return to the Logon.aspx.cs and add the VerifyPassword private helper method
as shown in the following code.
2.
private bool VerifyPassword(string suppliedUserName,
3.
string suppliedPassword )
4.
{
5.
bool passwordMatch = false;
6.
// Get the salt and pwd from the database
based on the user name.
7.
// See "How To: Use DPAPI (Machine
Store) from ASP.NET," "How To:
8.
// Use DPAPI (User Store) from Enterprise
Services," and "How To:
9.
// Create a DPAPI Library" for more
information about how to use
10.
// DPAPI to securely store connection strings.
11.
SqlConnection conn = new SqlConnection( "Server=(local);" +
12.
"Integrated
13.
Security=SSPI;"
+
14.
"database=UserAccounts");
15.
SqlCommand cmd = new SqlCommand( "LookupUser", conn );
16.
cmd.CommandType = CommandType.StoredProcedure;
17.
//Usage of Sql parameters also helps avoid SQL Injection attacks.
18.
SqlParameter sqlParam = cmd.Parameters.Add("@userName",
19.
SqlDbType.VarChar,
20.
20);
21.
sqlParam.Value = suppliedUserName;
22.
try
23.
{
24.
conn.Open();
25.
SqlDataReader reader = cmd.ExecuteReader();
26.
reader.Read(); // Advance to the one and only row
27.
// Return output parameters from returned data stream
28.
string dbPasswordHash = reader.GetString(0);
29.
int saltSize = 5;
30.
string salt =
31.
dbPasswordHash.Substring(dbPasswordHash.Length - saltSize);
32.
reader.Close();
33.
// Now take the password supplied by the user
34.
// and generate the hash.
35.
string hashedPasswordAndSalt =
36.
CreatePasswordHash(suppliedPassword, salt);
37.
// Now verify them.
38.
passwordMatch = hashedPasswordAndSalt.Equals(dbPasswordHash);
39.
}
40.
catch (Exception ex)
41.
{
42.
throw new Exception("Execption verifying password. " +
43.
ex.Message);
44.
}
45.
finally
46.
{
47.
conn.Close();
48.
}
49.
return passwordMatch;
50.}
Step 7. Test the Application
This procedure tests the application. You will register a user, which results in
the user name, password hash and salt value being added to the Users table
in the UserAccounts database. You will then log on the same user to ensure
the correct operation of the password verification routines.
To test the application
-
Return to the Logon form and double-click the Logon button to create a button
click event handler.
-
Add the following code to the Logon button click event handler to call the
VerifyPassword method and display a message based on whether or not the supplied
user name and password are valid.
3.
bool passwordVerified = false;
4.
try
5.
{
6.
passwordVerified =
7.
VerifyPassword(txtUserName.Text,txtPassword.Text);
8.
}
9.
catch(Exception ex)
10.{
11.
lblMessage.Text = ex.Message;
12.
return;
13.}
14.if (passwordVerified == true )
15.{
16.
// The user is authenticated
17.
// At this point, an authentication ticket is normally created
18.
// This can subsequently be used to generate a GenericPrincipal
19.
// object for .NET authorization purposes
20.
// For details, see "How To: Use Forms authentication with
21.
// GenericPrincipal objects
22.
lblMessage.Text = "Logon successful: User is authenticated";
23.}
24.else
25.{
26.
lblMessage.Text = "Invalid username or password";
27.}
-
On the Build menu, click Build Solution.
-
In Solution Explorer, right-click logon.aspx, and then click View in Browser.
-
Enter a user name and password, and then click Register.
-
Use SQL Server Enterprise Manager to view the contents of the Users table.
You should see a new row for the new user name together with a generated password
hash.
-
Return to the Logon Web page, re-enter the password, and then click Logon.
You should see the message "Logon successful: User is authenticated."
-
Now enter an invalid password (leaving the user name the same). You should see the
message "Invalid username or password."
-
Close Internet Explorer.
|