Manchmal kann es Sinn machen, nicht den standardmäßigen ASP.NET MembershipProvider zu nutzen. Daher möchte ich euch kurz erklären, wie ihr einen eigenen MembershipProvider schreiben könnt. Dabei ist es letztendlich euch überlassen, wo die Daten gespeichert sind.

Ich benutze bei einem Projekt etwa eine SQL-Datenbank und speicher bzw. lese die Daten per Stored-Procedures. Man könnte die Daten aber auch in einer XML-Datei speichern oder direkt hardcoded in der Klasse.

Als erstes erstellen wir ein neues Projekt in Visual Studio. Alternativ könnt ihr auch eine neue Klasse in einem bestehenden Projekt anlegen. Ich habe es als neues Projekt unterhalb meiner Projektmappe angelegt, der Übersicht halber.

Nun erstellen wir eine Klasse und leiten sie vom MembershipProvider ab:

using System;
using System.Configuration;
using System.Configuration.Provider;
using System.Data;
using System.Security.Cryptography;
using System.Text;
using System.Web.Security;
using System.Data.SqlClient;

namespace MyApp
{
    public class PersonalMembershipProvider : MembershipProvider
    {
        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            throw new NotImplementedException();
        }

        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            throw new NotImplementedException();
        }

        public override bool ValidateUser(string username, string password)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override string ApplicationName
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public override MembershipPasswordFormat PasswordFormat
        {
            get { throw new NotImplementedException(); }
        }
    }
}

Oben sind nicht alle Methoden / Attribute aufgelistet, der Übersicht halber. Eine Methode wird standardmäßig nicht überschrieben, ist meiner Meinung aber sehr wichtig. Per „Initialize()“ können Werte aus der „web.config“ des Zielprojektes an den RoleProvider übergeben werden. Diese können etwa den SQL-ConnectionString etc. enthalten. Hierbei gibt es eigentlich keine Vorgaben.

        public override void Initialize(string name, NameValueCollection config)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            if (string.IsNullOrEmpty(name))
            {
                name = "MyPersonalMembershipProvider";
            }
            base.Initialize(name, config);

            // ConnectionString auslesen
            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[config["connectionStringName"]];

            if ((connectionStringSettings == null) || (connectionStringSettings.ConnectionString.Trim() == String.Empty))
            {
                throw new ProviderException("Connection string cannot be blank.");
            }
            this._connectionString = connectionStringSettings.ConnectionString;
        }

In diesem Beispiel wird etwa mit der Zeile „ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[config[„connectionStringName“]];“ der Connectionstring aus der „web.config“ ausgelesen. Dazu wird der ConnectionStringName mit übergeben, wodurch über den ConfigurationManager der String ausgelesen werden kann. Weiterhin könnte man etwa übergeben, in welchem Format die Passwörter in der Datenbank gespeichert werden.

Nachdem ihr die Methoden entsprechend euren Bedürfnissen ausprogrammiert habt, wird es Zeit den MembershipProvider in eurem ASP.NET-Projekt einzubinden.
Dies geht relativ einfach. Für eine SQL-Verbindung benötigen wir einen entsprechenden ConnectionString. Sollte dieser noch nicht existieren oder die Benutzerdaten in einer anderen Datenbank liegen, legt einen entsprechenden Eintrag in der „web.config“ an. Desweiteren müsst ihr unter <membership> einen Eintrag anlegen, der auf den eigenen MembershipProvider verweißt. Solltet ihr mehre MembershipProvider nutzen, so solltet ihr angeben, welches der Standardprovider ist (defaultProvider).

<configuration>
  <connectionStrings>
    <add name="MSPConnString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|userdata.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" />
  </connectionStrings>

  <system.web>
    <membership defaultProvider="MyPersonalMembershipProvider">
      <providers>
        <clear />
        <add name="MyPersonalMembershipProvider" type="MyApp.PersonalMembershipProvider" connectionStringName="MSPConnString" passwordFormat="Hashed" />
      </providers>
    </membership>
  </system.web>
</configuration>

Ich habe in dem Beispiel noch einen Wert mit übergeben. Der sagt aus, dass ich meine Passwörter in der Datenbank gehasht ablegen möchte.
Dies muss ich natürlich ausprogrammieren.
Der MembershipProvider ist nun einsatzbereit.