I've encountered many instances lately in which i'm developing a new version of a site with an existing (custom) authentication database. Now, in cases like these, most .net developers would suggest writing your own membership and role providers to tie directly in to the existing schema; however, instead of rolling my own, I've decided to take a different approach in which I simply utilize the events provided with the login control to manually authenticate and migration the legacy accounts in real time. This approach requires considerably less code and allows you to utilize the default providers while still supporting the legacy user database. The event code would look something like this: (*note* that the db code makes use of classes and methods from a custom library)
protected void Login1_Authenticate(object sender, System.Web.UI.WebControls.AuthenticateEventArgs e)
{ // first, check to see if the user has already been migrated. if so, then were done here.
if(Membership.ValidateUser(Login1.UserName, Login1.Password))
{
e.Authenticated = true;
return;
}
else
{
// check legacy credentials
DataParameters parameters = new DataParameters();
parameters.Add("@Login", SqlDbType.VarChar, Login1.UserName);
parameters.Add("@Password", SqlDbType.VarChar, Login1.Password);
parameters.Add("@Email", SqlDbType.VarChar, 50, ParameterDirection.Output);
parameters.Add("@UserId", SqlDbType.Int, 1, ParameterDirection.Output);
parameters.Add("ReturnValue", SqlDbType.Int, 1, ParameterDirection.ReturnValue);
DataUtility.ExecuteNonQuery("ConnectionString", CommandType.StoredProcedure, "ValidateUser", parameters);
// if the credentials are good, then migrate to membership
if((int)parameters["ReturnValue"].Value == 0)
{
// migrate the user account
MembershipCreateStatus status;
MembershipUser newUser = Membership.CreateUser(Login1.UserName, Login1.Password, parameters["@Email"].Value.ToString(), "What is your Username?", Login1.UserName, true, out status);
if (status == MembershipCreateStatus.Success)
{
// update legacy user with new membership user id, tying the old to the new
parameters = new DataParameters("@UserId", SqlDbType.Int, Login1.UserName);
parameters.Add("@MembershipUserId", SqlDbType.UniqueIdentifier, newUser.ProviderUserKey);
DataUtility.ExecuteNonQuery("ConnectionString", CommandType.StoredProcedure, "UpdateUser", parameters);
// Create an empty Profile for the newly created user
ProfileCommon profile = (ProfileCommon)ProfileCommon.Create(Login1.UserName, true);
// Populate default profile values
profile.Theme = "Default";
// Save the profile
profile.Save();
e.Authenticated = true;
return;
}
else
Login1.FailureText = "We were unable to migrate you user account. Please contact support for further assistance.";
}
e.Authenticated = false;
}
So, with the little bit of code above, I'm able to authenticate and migrate legacy user accounts to the new membership system without breaking the existing db schema. It may not be as elegant as writing your own provider, but in my case, it was equally as effective.