MySql Membership provider i .NET 2.0
Förord
I .NET 2.0 finns det inbyggt stöd för rollbaserad medlemshantering. För att spara och hantera medlemmar implementerar man en membershipprovider vilken består av ett gäng klasser och metoder för att utföra olika aktiviteter i medlemssystemet, samt en databas eller någon annan lagringsform t.ex. XML-filer för att lagra data.
Hämta klasserna
För er som inte orkar läsa denna artikeln kan ni ladda ner de viktigaste klasserna här och sedan labba själva.Default providern som följer med .NET är en SqlMembershipProvider och en SqlRoleProvider vilket tillåter att man har antingen en SQL eller SQLExpress databas som lagringsform.
Men det går att överrida dessa klasser så att man kan använda andra providers som exempelvis lagrar data i en MySql databas istället. Det är detta jag skall visa i denna artikel.
Dessutom kommer jag att visa hur man utökar MembershipUser klassen så att den även innehåller fält för FirstName och LastName.
OK, till verket.
Hämta nödvändiga filer
1) Se till att du laddar ner MySql .NET connectorn från www.mysql.com och lägg den i mappen /bin i din applikation.
2) Ladda ner zip-filen härifrån med klasserna som överrider default providern för Membership och role och lägg klasserna i din App_code mapp. I zip-filen finns även en.sql fil som innehåller strukturen för de tre tabellerna i MySql databasen. Kör denna mot din befintliga MySql server så kommer du få en ny databas som heter aspnetdb.
Web.config inställningar
1) Skapa en web.config fil i din applikation om du inte redan gjort det. I denna fil skall vi lägga till några element.
Vi börjar med
Name="MySqlConnection" />
2) Nu skall vi lägga till ett element vilket anger vår default MembershipProvider, detta gör vi innanför elementet system.web:
name="MySqlMembershipProvider"
connectionStringName="MySqlConnection"
applicationName="/"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="false"
passwordFormat="Clear"
encryptionKey="AB56FE8EA700B42A"
type="Webpublic.MemberSystem.MySqlMembershipProvider"
/>
Observera parametrarna där vi kan slå av och på olika funktioner som uniqueEmail.
MySQLMembershipUser
Tidigare skrev jag att vi skulle lägga till egna fält för FirstName och LastName i MemberShip providern. För att göra detta måste vi lägga till properties för detta på klassen MembershipUser.cs
1) Vi skapar en egen klass som vi kallar för MySQLMembershipUser och ärver från MembershipUser. Sedan implementerar vi några egna properties för FirstName och LastName.
public class MySQLMembershipUser : MembershipUser
{
// Properties that extends the base class
private string _FirstName;
private string _LastName;
public string FirstName
{
get { return _FirstName; }
set { _FirstName = value; }
}
public string LastName
{
get { return _LastName; }
set { _LastName = value; }
}
}
No problems so far.
2) Vi lägger nu till våra nya properties i vår nya klassimplementation tillsammans med de properties som redan finns i basen.
public MySQLMembershipUser(string providername,
string username,
object providerUserKey,
string email,
string passwordQuestion,
string comment,
bool isApproved,
bool isLockedOut,
DateTime creationDate,
DateTime lastLoginDate,
DateTime lastActivityDate,
DateTime lastPasswordChangedDate,
DateTime lastLockedOutDate,
string firstname,
string lastname)
:
base(providername,
username,
providerUserKey,
email,
passwordQuestion,
comment,
isApproved,
isLockedOut,
creationDate,
lastLoginDate,
lastActivityDate,
lastPasswordChangedDate,
lastLockedOutDate)
{
this.FirstName = firstname;
this.LastName = lastname;
}
Nu är MySQLMembershipUser klar att användas tillsammans med vår MembershipProvider.
MySqlMembershipProvider
1) Låt oss titta på en liten kodsnutt från MySqlMembershipProvider.cs som överrider defaultprovidern:
Vi talar om att klassen skall ärva från MembershipProvider så att vi kan överrida de metoder vi vill:
// Inherit from MembershipProvider
public sealed class MySqlMembershipProvider : MembershipProvider
Sedan överridar vi de klasser vi måste för att kunna koppla upp oss mot vår MySql databas istället bland annat initialize metoden där vi hämtar information från web.config och definerar connection strings.
Eftersom vi har med två extra parametrar i vår MembershipUser klass och metoden CreateUser som vi överrider bara kan returnera av typen MembershipUser och inte MySQLMembershipUser måste vi överlasta metoden.
2) Vi skapar först vår överridna metod som returnerar ett MembershipUser objekt, men vi returnerar vår överlastade metod för CreateUser fast med tomma parametrar för FirstName och LastName.
public override MembershipUser CreateUser(string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
// Return the overloaded method
return this.CreateUser(
"",
"",
username,
password,
email,
passwordQuestion,
passwordAnswer,
isApproved,
providerUserKey,
out status);
}
3) Låt oss titta på vår överlastade metod. Den tar självklart våra FirstName och LastName parametrar.
public MySQLMembershipUser CreateUser(string FirstName,
string LastName,
string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
4) För att returnera ett objekt som nu är av typen MySQLMembershipUser så cast:ar vi vår GetUser() metod.
return (MySQLMembershipUser)GetUser(username, false);
5) För att kunna hämta alla data från databasen, även de nya FirstName och LastName värdena måste vi ändra metoden GetUserFromReader() och göra så att den returnerar en MySQLMembershipUser istället för en MembershipUser.
Här lägger vi också till parametrar för FirstName och LastName.
private MySQLMembershipUser GetUserFromReader(MySqlDataReader reader)
{
object providerUserKey = new Guid(reader.GetValue(0).ToString());
string FirstName = reader.IsDBNull(1) ? "" : reader.GetString(1);
string LastName = reader.IsDBNull(2) ? "" : reader.GetString(2);
6) I metoden UpdateUser som tar en parameter av typen MembershipUser måste vi även ändra lite. Vi cast:ar user objektet så att ett nytt objekt mUser blir av typen MySQLMembershipUser och använder detta för att populera parametrarna för FirstName och LastName.
public override void UpdateUser(MembershipUser user)
{
//...
// Cast the user object to be of type MySQLMembershipUser
MySQLMembershipUser mUser = (MySQLMembershipUser)user;
cmd.Parameters.Add("?FirstName", MySqlDbType.VarChar, 255).Value = mUser.FirstName;
cmd.Parameters.Add("?LastName", MySqlDbType.VarChar, 255).Value = mUser.LastName;
//...
}
MySqlRoleProvider
Nu är det dags att implementera roleprovidern som gör att vi kan tillhandahålla ett rollbaserat inloggningssystem.
1) Börja med web.config och lägg till en roleprovider under system.web elementet.
enabled="true"
cacheRolesInCookie="true"
defaultProvider="MySqlRoleProvider"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All">
name="MySqlRoleProvider"
connectionStringName="MySqlConnection"
applicationName="/"
type="Webpublic.MemberSystem.MySqlRoleProvider"
/>
2) Klassen som överrider default providern är ganska rätt fram, och överrider helt enkelt de metoder som behövs för att göra anrop mot databasen. Själva role tabellen och usersinroles är ganska enkla tabeller och behöver kanske inte förklaras så mycket.
Implementation
1) För att visa exempel på hur man implementerar membershipsystemet så skapar vi nu en Web Form som vi kallar för CreateUser.aspx.
2) Här kastar vi in en CreateUserWizard kontroll från toolboxen och skapar en egen template för att skapa en ny user.
Observera FirstName och LastName som är tillagda parametrar i systemet och som anges här.
3) Vi måste nu koppla en eventhandler till vår CreateUserWizard:
// Add eventhandler for CreatedUser
CreateUserWizard1.CreatedUser += new EventHandler(CreateUserWizard1_CreatedUser);
4) Och skapa metoden som skapar en ny användare:
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
// Get First- and Last name
TextBox txtFirstName =
(TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("FirstName");
TextBox txtLastName =
(TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("LastName");
TextBox userNameTextBox =
(TextBox)wizCreate.ContentTemplateContainer.FindControl("UserName");
TextBox Email =
(TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Email");
// Cast the user object of the GetUser() method to
// be of type MySQLMembershipUser
MySQLMembershipUser user = (MySQLMembershipUser)Membership.GetUser(userNameTextBox.Text);
// Add additional data
user.FirstName = txtFirstName.Text;
user.LastName = txtLastName.Text;
// Update the user in the database
Membership.UpdateUser(user);
// Get the labels
Label lblFullName =
(Label)wizComplete.ContentTemplateContainer.FindControl("lblFullName");
Label lblUserName =
(Label)wizComplete.ContentTemplateContainer.FindControl("lblUserName");
Label lblEmail =
(Label)wizComplete.ContentTemplateContainer.FindControl("lblEmail");
// Set the values to the labels
lblFullName.Text = txtFirstName.Text + " " + txtLastName.Text;
lblUserName.Text = userNameTextBox.Text;
lblEmail.Text = Email.Text;
}
Observera hur man hittar kontroller inuti wizarden, och hur vi cast:ar Membership.GetUser() till att vara av typen MySQLMembershipUser. Detta gör vi för att kunna spara förnamn och efternamn i databasen.
Detta var bara ett exempel på hur man kan skapa en ny användare i systemet.
Vidare kan man hantera roller och annat med Roles och Membership klasserna.
Pelle Johansson
http://www.derigomedia.com/hack/arkiv/hack20060927.html Grattis
Göran Hillborg
Intressant läsning! Det vore ännu mer intressant om du kunde utveckla med rollhantering etc. i en del 2!
Jesper Thörn
Rollhanteringsbiten är jag mest intresserad av. :)