Freigeben über


Verwenden der schreibgeschützten XML-basierten Beispielanbieter für Mitgliedschaften und Rollen mit IIS 7.0

von Robert McMurray

Einführung

Bei der Veröffentlichung von ASP.NET 2.0 wurden auf der Microsoft Developer Network(MSDN)-Website zwei Beispielanbieter für ASP.NET-Mitgliedschaften und -Rollen bereitgestellt. Diese schreibgeschützten Anbieter verwendeten XML-Dateien für die Liste der Benutzer und Rollen und waren unter den folgenden URLs verfügbar:

Diese Beispiele eignen sich hervorragend für die Verwendung mit IIS 7.0 und höher für Demonstrations- oder Testwebsites, aber wegen des Sicherheitskonzepts von IIS funktionieren sie nicht automatisch mit IIS. Nach der ursprünglichen Anleitung konnten Sie die Beispielanbieter für Mitgliedschaften/Rollen im Ordner „App_Code“ Ihrer Website bereitstellen, aber IIS erfordert, dass die Anbieter im globalen Assemblycache (GAC) registriert sind, bevor sie bereitgestellt werden können. Vor diesem Hintergrund werden Sie in den folgenden Schritten durch die Kompilierung und Bereitstellung der schreibgeschützten XML-Anbieter auf einem Entwicklungssystem geführt.

Voraussetzungen

Die folgenden Elemente sind erforderlich, um die Verfahren in diesem Artikel abzuschließen:

  1. IIS 7.0 oder höher muss auf Ihrem Windows Vista- oder Windows Server 2008-Computer installiert sein.
  2. ASP.NET muss für Ihre Version von IIS installiert sein.
  3. Der Internetinformationsdienste-Manager für IIS 7.0 und höher muss installiert sein.
  4. Sie benötigen Gacutil.exe auf Ihrem IIS-Computer, um die Assemblys zu Ihrem globalen Assemblycache (GAC) hinzufügen zu können.

Schritt 1: Einrichten der XML-Anbieterprojekte

In diesem ersten Schritt erstellen Sie eine Projektmappe in Visual Studio, die zwei Projekte enthält: eines für den XML-basierten Mitgliedschaftsanbieter und das andere für den XML-basierten Rollenanbieter.

  1. Öffnen Sie Microsoft Visual Studio 2008.

  2. Klicken Sie auf das Menü Datei, dann auf Neu und dann auf Projekt.

  3. Geben Sie im Dialogfeld Neues Projekt Folgendes ein:

    • Wählen Sie Visual C# als Projekttyp aus.
    • Wählen Sie Klassenbibliothek als Vorlage aus.
    • Geben Sie ReadOnlyXmlMembershipProvider als Projektnamen ein.
    • Geben Sie ReadOnlyXmlProviders als Projektmappennamen ein.
    • Klicken Sie auf OK.
  4. Entfernen Sie die Datei Class1.cs aus dem Projekt ReadOnlyXmlMembershipProvider:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Datei Class1.cs im Projekt ReadOnlyXmlMembershipProvider, und Löschen Sie sie dann.
    • Klicken Sie auf OK, wenn Sie aufgefordert werden, die Klasse dauerhaft zu löschen.
  5. Fügen Sie einen Verweispfad zur Bibliothek „System.Configuration“ hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlMembershipProvider, und wählen Sie dann Verweis hinzufügen… aus.
    • Klicken Sie auf die Registerkarte .NET.
    • Wählen Sie „System.Configuration“ in der Liste der Assemblys aus.
    • Klicken Sie auf OK.
  6. Fügen Sie einen Verweispfad zur Bibliothek „System.Web“ hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlMembershipProvider, und wählen Sie dann Verweis hinzufügen… aus.
    • Klicken Sie auf die Registerkarte .NET.
    • Wählen Sie „System.Web“ in der Liste der Assemblys aus.
    • Klicken Sie auf OK.
  7. Fügen Sie dem Projekt einen Schlüssel mit einem starken Namen hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlRoleProvider und dann auf Eigenschaften.
    • Klicken Sie auf die Registerkarte Signierung.
    • Aktivieren Sie das Kontrollkästchen Assembly signieren.
    • Wählen Sie aus dem Dropdownfeld mit starkem Schlüsselnamen <Neu…> aus.
    • Geben Sie ReadOnlyXmlMembershipProviderKey für den Schlüsseldateinamen ein.
    • Geben Sie bei Bedarf ein Kennwort für die Schlüsseldatei ein; deaktivieren Sie andernfalls das Kontrollkästchen Meine Schlüsseldatei mit einem Kennwort schützen.
    • Klicken Sie auf OK.
  8. (Optional) Fügen Sie ein benutzerdefiniertes Buildereignis hinzu, um die DLL automatisch im GAC zu registrieren:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlRoleProvider und dann auf Eigenschaften.

    • Klicken Sie auf die Registerkarte Buildereignisse.

    • Geben Sie im Feld Befehlszeile für Postbuildereignis Folgendes ein:

      call "%VS90COMNTOOLS%\vsvars32.bat">nul
      gacutil.exe /if "$(TargetPath)"
      
  9. Fügen Sie ein zweites Projekt zur Projektmappe hinzu:

    • Klicken Sie auf Datei, dann auf Hinzufügen und dann auf Neues Projekt….
    • Wählen Sie Visual C# als Projekttyp aus.
    • Wählen Sie Klassenbibliothek als Vorlage aus.
    • Geben Sie ReadOnlyXmlRoleProvider als Namen des Projekts ein.
    • Klicken Sie auf OK.
  10. Entfernen Sie die Datei Class1.cs aus dem Projekt ReadOnlyXmlRoleProvider:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Datei Class1.cs im Projekt ReadOnlyXmlRoleProvider, und Löschen Sie sie dann.
    • Klicken Sie auf OK, wenn Sie aufgefordert werden, die Klasse dauerhaft zu löschen.
  11. Fügen Sie einen Verweispfad zur Bibliothek „System.Configuration“ hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlRoleProvider und dann auf Verweis hinzufügen….
    • Klicken Sie auf die Registerkarte .NET.
    • Wählen Sie „System.Configuration“ in der Liste der Assemblys aus.
    • Klicken Sie auf OK.
  12. Fügen Sie einen Verweispfad zur Bibliothek „System.Web“ hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlRoleProvider und dann auf Verweis hinzufügen….
    • Klicken Sie auf die Registerkarte .NET.
    • Wählen Sie „System.Web“ in der Liste der Assemblys aus.
    • Klicken Sie auf OK.
  13. Fügen Sie dem Projekt einen Schlüssel mit einem starken Namen hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlRoleProvider und dann auf Eigenschaften.
    • Klicken Sie auf die Registerkarte Signierung.
    • Aktivieren Sie das Kontrollkästchen Assembly signieren.
    • Wählen Sie aus dem Dropdownfeld mit starkem Schlüsselnamen <Neu…> aus.
    • Geben Sie ReadOnlyXmlRoleProvider für den Schlüsseldateinamen ein.
    • Geben Sie bei Bedarf ein Kennwort für die Schlüsseldatei ein; deaktivieren Sie andernfalls das Kontrollkästchen Meine Schlüsseldatei mit einem Kennwort schützen.
    • Klicken Sie auf OK.
  14. (Optional) Fügen Sie ein benutzerdefiniertes Buildereignis hinzu, um die DLL automatisch im GAC zu registrieren:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlRoleProvider und dann auf Eigenschaften.

    • Klicken Sie auf die Registerkarte Buildereignisse.

    • Geben Sie im Feld Befehlszeile für Postbuildereignis Folgendes ein:

      call "%VS90COMNTOOLS%\vsvars32.bat">nul
      gacutil.exe /if "$(TargetPath)"
      
  15. Speichern Sie die Projektmappe.

Schritt 2: Hinzufügen der Anbieterklassen für die Projekte

Im zweiten Schritt erstellen Sie die Klassen für die XML-basierten Mitgliedschafts- und Rollenanbieter. Der Code für diese Klassen wurde aus den Themen Mitgliedschaftsanbieter und Rollenanbieter auf MSDN kopiert.

  1. Fügen Sie eine neue Klasse zum Projekt ReadOnlyXmlMembershipProvider hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlMembershipProvider, dann auf Hinzufügen und dann auf Klasse….

    • Benennen Sie die Klasse ReadOnlyXmlMembershipProvider.cs.

    • Klicken Sie auf Hinzufügen.

    • Entfernen Sie den vorhandenen Code.

    • Fügen Sie den folgenden Beispielcode aus dem Thema Mitgliedschaftsanbieter in den Editor ein:

      using System;
      using System.Xml;
      using System.Collections.Generic;
      using System.Collections.Specialized;
      using System.Configuration.Provider;
      using System.Web.Security;
      using System.Web.Hosting;
      using System.Web.Management;
      using System.Security.Permissions;
      using System.Web;
      
      public class ReadOnlyXmlMembershipProvider : MembershipProvider
      {
         private Dictionary<string, MembershipUser> _Users;
         private string _XmlFileName;
      
         // MembershipProvider Properties
         public override string ApplicationName
         {
            get { throw new NotSupportedException(); }
            set { throw new NotSupportedException(); }
         }
      
         public override bool EnablePasswordRetrieval
         {
            get { return false; }
         }
      
         public override bool EnablePasswordReset
         {
            get { return false; }
         }
      
         public override int MaxInvalidPasswordAttempts
         {
            get { throw new NotSupportedException(); }
         }
      
         public override int MinRequiredNonAlphanumericCharacters
         {
            get { throw new NotSupportedException(); }
         }
      
         public override int MinRequiredPasswordLength
         {
            get { throw new NotSupportedException(); }
         }
      
         public override int PasswordAttemptWindow
         {
            get { throw new NotSupportedException(); }
         }
      
         public override MembershipPasswordFormat PasswordFormat
         {
            get { throw new NotSupportedException(); }
         }
      
         public override string PasswordStrengthRegularExpression
         {
            get { throw new NotSupportedException(); }
         }
      
         public override bool RequiresQuestionAndAnswer
         {
            get { throw new NotSupportedException(); }
         }
      
         public override bool RequiresUniqueEmail
         {
            get { throw new NotSupportedException(); }
         }
      
         // MembershipProvider Methods
         public override void Initialize(string name,
            NameValueCollection config)
         {
            // Verify that config isn't null
            if (config == null)
               throw new ArgumentNullException("config");
            // Assign the provider a default name if it doesn't have one
            if (String.IsNullOrEmpty(name))
               name = "ReadOnlyXmlMembershipProvider";
            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
               config.Remove("description");
               config.Add("description",
                  "Read-only XML membership provider");
            }
            // Call the base class's Initialize method
            base.Initialize(name, config);
            // Initialize _XmlFileName and make sure the path
            // is app-relative
            string path = config["xmlFileName"];
            if (String.IsNullOrEmpty(path))
               path = "~/App_Data/Users.xml";
            if (!VirtualPathUtility.IsAppRelative(path))
               throw new ArgumentException
                  ("xmlFileName must be app-relative");
            string fullyQualifiedPath = VirtualPathUtility.Combine
               (VirtualPathUtility.AppendTrailingSlash
               (HttpRuntime.AppDomainAppVirtualPath), path);
            _XmlFileName = HostingEnvironment.MapPath(fullyQualifiedPath);
            config.Remove("xmlFileName");
            // Make sure we have permission to read the XML data source and
            // throw an exception if we don't
            FileIOPermission permission =
               new FileIOPermission(FileIOPermissionAccess.Read,
                  _XmlFileName);
            permission.Demand();
            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
               string attr = config.GetKey(0);
               if (!String.IsNullOrEmpty(attr))
                  throw new ProviderException
                      ("Unrecognized attribute: " + attr);
            }
         }
      
         public override bool ValidateUser(string username, string password)
         {
            // Validate input parameters
            if (String.IsNullOrEmpty(username) ||
               String.IsNullOrEmpty(password))
                  return false;
            try
            {
               // Make sure the data source has been loaded
               ReadMembershipDataStore();
               // Validate the user name and password
               MembershipUser user;
               if (_Users.TryGetValue(username, out user))
               {
                  if (user.Comment == password) // Case-sensitive
                  {
                     // NOTE: A read/write membership provider
                     // would update the user's LastLoginDate here.
                     // A fully featured provider would also fire
                     // an AuditMembershipAuthenticationSuccess
                     // Web event
                     return true;
                  }
               }
               // NOTE: A fully featured membership provider would
               // fire an AuditMembershipAuthenticationFailure
               // Web event here
               return false;
            }
            catch (Exception)
            {
               return false;
            }
         }
      
         public override MembershipUser GetUser(string username,
            bool userIsOnline)
         {
            // Note: This implementation ignores userIsOnline
            // Validate input parameters
               if (String.IsNullOrEmpty(username))
               return null;
            // Make sure the data source has been loaded
            ReadMembershipDataStore();
            // Retrieve the user from the data source
            MembershipUser user;
            if (_Users.TryGetValue(username, out user))
               return user;
            return null;
         }
      
         public override MembershipUserCollection GetAllUsers(int pageIndex,
            int pageSize, out int totalRecords)
         {
            // Note: This implementation ignores pageIndex and pageSize,
            // and it doesn't sort the MembershipUser objects returned
            // Make sure the data source has been loaded
            ReadMembershipDataStore();
            MembershipUserCollection users =
               new MembershipUserCollection();
            foreach (KeyValuePair<string, MembershipUser> pair in _Users)
               users.Add(pair.Value);
            totalRecords = users.Count;
            return users;
         }
      
         public override int GetNumberOfUsersOnline()
         {
            throw new NotSupportedException();
         }
      
         public override bool ChangePassword(string username,
            string oldPassword, string newPassword)
         {
            throw new NotSupportedException();
         }
      
         public override bool
            ChangePasswordQuestionAndAnswer(string username,
            string password, string newPasswordQuestion,
            string newPasswordAnswer)
         {
            throw new NotSupportedException();
         }
      
         public override MembershipUser CreateUser(string username,
            string password, string email, string passwordQuestion,
            string passwordAnswer, bool isApproved, object providerUserKey,
            out MembershipCreateStatus status)
         {
            throw new NotSupportedException();
         }
      
         public override bool DeleteUser(string username,
            bool deleteAllRelatedData)
         {
            throw new NotSupportedException();
         }
      
         public override MembershipUserCollection
            FindUsersByEmail(string emailToMatch, int pageIndex,
            int pageSize, out int totalRecords)
         {
            throw new NotSupportedException();
         }
      
         public override MembershipUserCollection
            FindUsersByName(string usernameToMatch, int pageIndex,
            int pageSize, out int totalRecords)
         {
            throw new NotSupportedException();
         }
      
         public override string GetPassword(string username, string answer)
         {
            throw new NotSupportedException();
         }
      
         public override MembershipUser GetUser(object providerUserKey,
            bool userIsOnline)
         {
            throw new NotSupportedException();
         }
      
         public override string GetUserNameByEmail(string email)
         {
            throw new NotSupportedException();
         }
      
         public override string ResetPassword(string username,
            string answer)
         {
            throw new NotSupportedException();
         }
      
         public override bool UnlockUser(string userName)
         {
            throw new NotSupportedException();
         }
      
         public override void UpdateUser(MembershipUser user)
         {
            throw new NotSupportedException();
         }
      
         // Helper method
         private void ReadMembershipDataStore()
         {
            lock (this)
            {
               if (_Users == null)
               {
                  _Users = new Dictionary<string, MembershipUser>
                     (16, StringComparer.InvariantCultureIgnoreCase);
                  XmlDocument doc = new XmlDocument();
                  doc.Load(_XmlFileName);
                  XmlNodeList nodes = doc.GetElementsByTagName("User");
                  foreach (XmlNode node in nodes)
                  {
                     MembershipUser user = new MembershipUser(
                        Name,                       // Provider name
                        node["UserName"].InnerText, // Username
                        null,                       // providerUserKey
                        node["EMail"].InnerText,    // Email
                        String.Empty,               // passwordQuestion
                        node["Password"].InnerText, // Comment
                        true,                       // isApproved
                        false,                      // isLockedOut
                        DateTime.Now,               // creationDate
                        DateTime.Now,               // lastLoginDate
                        DateTime.Now,               // lastActivityDate
                        DateTime.Now,               // lastPasswordChangedDate
                        new DateTime(1980, 1, 1)    // lastLockoutDate
                     );
                     _Users.Add(user.UserName, user);
                  }
               }
            }
         }
      }
      
  2. Fügen Sie eine neue Klasse zum Projekt ReadOnlyXmlRoleProvider hinzu:

    • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt ReadOnlyXmlRoleProvider, dann auf Hinzufügen und dann auf Klasse….

    • Benennen Sie die Klasse ReadOnlyXmlRoleProvider.cs.

    • Klicken Sie auf Hinzufügen.

    • Entfernen Sie den vorhandenen Code.

    • Fügen Sie den folgenden Beispielcode aus dem Thema Rollenanbieter in den Editor ein:

      using System;
      using System.Web.Security;
      using System.Collections.Generic;
      using System.Collections.Specialized;
      using System.Configuration.Provider;
      using System.Web.Hosting;
      using System.Xml;
      using System.Security.Permissions;
      using System.Web;
      
      public class ReadOnlyXmlRoleProvider : RoleProvider
      {
         private Dictionary<string, string[]> _UsersAndRoles =
         new Dictionary<string, string[]>(16,
         StringComparer.InvariantCultureIgnoreCase);
      
         private Dictionary<string, string[]> _RolesAndUsers =
            new Dictionary<string, string[]>(16,
            StringComparer.InvariantCultureIgnoreCase);
      
         private string _XmlFileName;
      
         // RoleProvider properties
         public override string ApplicationName
         {
            get { throw new NotSupportedException(); }
            set { throw new NotSupportedException(); }
         }
      
         // RoleProvider methods
         public override void Initialize(string name,
         NameValueCollection config)
         {
            // Verify that config isn't null
            if (config == null)
               throw new ArgumentNullException("config");
            // Assign the provider a default name if it doesn't have one
            if (String.IsNullOrEmpty(name))
               name = "ReadOnlyXmlRoleProvider";
            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
               config.Remove("description");
               config.Add("description", "Read-only XML role provider");
            }
            // Call the base class's Initialize method
            base.Initialize(name, config);
            // Initialize _XmlFileName and make sure the path
            // is app-relative
            string path = config["xmlFileName"];
            if (String.IsNullOrEmpty(path))
               path = "~/App_Data/Users.xml";
            if (!VirtualPathUtility.IsAppRelative(path))
               throw new ArgumentException
                  ("xmlFileName must be app-relative");
            string fullyQualifiedPath = VirtualPathUtility.Combine
               (VirtualPathUtility.AppendTrailingSlash
               (HttpRuntime.AppDomainAppVirtualPath), path);
            _XmlFileName = HostingEnvironment.MapPath(fullyQualifiedPath);
            config.Remove("xmlFileName");
            // Make sure we have permission to read the XML data source and
            // throw an exception if we don't
            FileIOPermission permission =
               new FileIOPermission(FileIOPermissionAccess.Read,
                  _XmlFileName);
            permission.Demand();
            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
               string attr = config.GetKey(0);
               if (!String.IsNullOrEmpty(attr))
                  throw new ProviderException
                     ("Unrecognized attribute: " + attr);
            }
            // Read the role data source. NOTE: Unlike
            // ReadOnlyXmlMembershipProvider, this provider can
            // read the data source at this point because Read-
            // RoleDataStore doesn't call into the role manager
            ReadRoleDataStore();
         }
      
         public override bool IsUserInRole(string username, string roleName)
         {
            // Validate input parameters
            if (username == null || roleName == null)
               throw new ArgumentNullException();
            if (username == String.Empty || roleName == string.Empty)
               throw new ArgumentException();
            // Make sure the user name and role name are valid
            if (!_UsersAndRoles.ContainsKey(username))
               throw new ProviderException("Invalid user name");
            if (!_RolesAndUsers.ContainsKey(roleName))
               throw new ProviderException("Invalid role name");
            // Determine whether the user is in the specified role 
            string[] roles = _UsersAndRoles[username];
            foreach (string role in roles)
            {
               if (String.Compare(role, roleName, true) == 0)
                  return true;
            }
            return false;
         }
      
         public override string[] GetRolesForUser(string username)
         {
            // Validate input parameters
            if (username == null)
               throw new ArgumentNullException();
            if (username == string.Empty)
               throw new ArgumentException();
            // Make sure the user name is valid
            string[] roles;
            if (!_UsersAndRoles.TryGetValue(username, out roles))
               throw new ProviderException("Invalid user name");
            // Return role names
            return roles;
         }
      
         public override string[] GetUsersInRole(string roleName)
         {
            // Validate input parameters
            if (roleName == null)
               throw new ArgumentNullException();
            if (roleName == string.Empty)
            throw new ArgumentException();
            // Make sure the role name is valid
            string[] users;
            if (!_RolesAndUsers.TryGetValue(roleName, out users))
               throw new ProviderException("Invalid role name");
            // Return user names
            return users;
         }
      
         public override string[] GetAllRoles()
         {
            int i = 0;
            string[] roles = new string[_RolesAndUsers.Count];
            foreach (KeyValuePair<string, string[]> pair in _RolesAndUsers)
               roles[i++] = pair.Key;
            return roles;
         }
      
         public override bool RoleExists(string roleName)
         {
            // Validate input parameters
            if (roleName == null)
               throw new ArgumentNullException();
            if (roleName == string.Empty)
               throw new ArgumentException();
            // Determine whether the role exists
            return _RolesAndUsers.ContainsKey(roleName);
         }
      
         public override void CreateRole(string roleName)
         {
            throw new NotSupportedException();
         }
      
         public override bool DeleteRole(string roleName,
            bool throwOnPopulatedRole)
         {
            throw new NotSupportedException();
         }
      
         public override void AddUsersToRoles(string[] usernames,
            string[] roleNames)
         {
            throw new NotSupportedException();
         }
      
         public override string[] FindUsersInRole(string roleName,
            string usernameToMatch)
         {
            throw new NotSupportedException();
         }
      
         public override void RemoveUsersFromRoles(string[] usernames,
            string[] roleNames)
         {
            throw new NotSupportedException();
         }
      
         // Helper method
         private void ReadRoleDataStore()
         {
            XmlDocument doc = new XmlDocument();
            doc.Load(_XmlFileName);
            XmlNodeList nodes = doc.GetElementsByTagName("User");
            foreach (XmlNode node in nodes)
            {
               if (node["UserName"] == null)
                  throw new ProviderException
                     ("Missing UserName element");
               string user = node["UserName"].InnerText;
               if (String.IsNullOrEmpty(user))
                  throw new ProviderException("Empty UserName element");
               if (node["Roles"] == null ||
                  String.IsNullOrEmpty(node["Roles"].InnerText))
                     _UsersAndRoles.Add(user, new string[0]);
               else
               {
                  string[] roles = node["Roles"].InnerText.Split(',');
                  // Add the role names to _UsersAndRoles and
                  // key them by user name
                  _UsersAndRoles.Add(user, roles);
                  foreach (string role in roles)
                  {
                     // Add the user name to _RolesAndUsers and
                     // key it by role names
                     string[] users1;
                     if (_RolesAndUsers.TryGetValue(role, out users1))
                     {
                        string[] users2 =
                           new string[users1.Length + 1];
                        users1.CopyTo(users2, 0);
                        users2[users1.Length] = user;
                        _RolesAndUsers.Remove(role);
                        _RolesAndUsers.Add(role, users2);
                     }
                     else
                        _RolesAndUsers.Add(role,
                     new string[] { user });
                  }
               }
            }
         }
      }
      
  3. Speichern und kompilieren Sie beide Projekte.

Hinweis

Wenn Sie die optionalen Schritte zur Registrierung der Assemblys im GAC nicht verwendet haben, müssen Sie die Assemblys manuell auf Ihren IIS-Computer kopieren und die Assemblys mit dem Tool „Gacutil.exe“ zum GAC hinzufügen. Weitere Informationen finden Sie im folgenden Thema auf der Microsoft MSDN-Website:

Schritt 3: Hinzufügen der Anbieter zu IIS

Im dritten Schritt bestimmen Sie die Assemblyinformationen für die Mitgliedschafts- und Rollenanbieter und fügen diese Informationen dann zur Liste der vertrauenswürdigen Anbieter für IIS hinzu.

  1. Ermitteln Sie die Assemblyinformationen für beide Anbieter:

    • Öffnen Sie im Windows-Explorer den Pfad C:\Windows\assembly, wobei „C:“ Ihr Betriebssystemlaufwerk ist.
    • Suchen Sie die Assemblys ReadOnlyXmlMembershipProvider und ReadOnlyXmlRoleProvider.
    • Klicken Sie mit der rechten Maustaste auf jedes Assembly, und klicken Sie dann auf Eigenschaften.
    • Kopieren Sie die Werte von Kultur, z. B. Neutral.
    • Kopieren Sie die Nummern der Version, z. B. 1.0.0.0.
    • Kopieren Sie die Werte von Öffentliches Schlüsseltoken, z. B. 426f62526f636b73.
    • Klicken Sie auf Abbrechen.
  2. Fügen Sie die XML-Anbieter zur Liste der vertrauenswürdigen Anbieter für IIS hinzu:

    • Öffnen Sie die Datei „Administration.config“ zur Bearbeitung.

      Hinweis

      Diese Datei befindet sich in Ihrem Ordner unter %WinDir%\System32\Inetsrv\Config.

    • Fügen Sie die Anbieter mit den Assemblyeigenschaften aus den vorherigen Schritten zum Abschnitt <trustedProviders> mit der folgenden Syntax hinzu:

      <add type="ReadOnlyXmlMembershipProvider, ReadOnlyXmlMembershipProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73" />
      
      <add type="ReadOnlyXmlRoleProvider, ReadOnlyXmlRoleProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73" />
      
    • Speichern und schließen Sie die Datei „Administration.config“.

Schritt 4: Konfigurieren einer Site für die Formularauthentifizierung mit den XML-Anbietern

Im vierten Schritt konfigurieren Sie eine Website für die Verwendung der Formularauthentifizierung mit den XML-basierten Mitgliedschafts- und Rollenanbietern. Dazu erstellen Sie manuell eine „Web.config“-Datei für Ihre Website, fügen Sie eine XML-Datei mit der Liste der Benutzer zum Ordner „App_Data“ der Website hinzu und fügen Sie eine „Login.aspx“-Seite zur Website hinzu, die Anforderungen zur Formularauthentifizierung verarbeitet.

  1. Erstellen Sie eine XML-Datei für die Mitgliedschaftsbenutzer und Rollen:

    • Fügen Sie den folgenden Code in einem Text-Editor ein:

      <Users>
         <User>
            <UserName>Bob</UserName>
            <Password>contoso!</Password>
            <EMail>bob@contoso.com</EMail>
            <Roles>Members</Roles>
         </User>
         <User>
            <UserName>Alice</UserName>
            <Password>contoso!</Password>
            <EMail>alice@contoso.com</EMail>
            <Roles>Members,Administrators</Roles>
         </User>
      </Users>
      
    • Speichern Sie den Code als „Users.xml“ im Ordner „App_Data“ Ihrer Website.

  2. Erstellen Sie eine „Login.aspx“-Datei für Ihre Website:

    • Fügen Sie den folgenden Code in einem Text-Editor ein:

      <%@ Page Language="C#" %>
      <%@ Import Namespace="System.ComponentModel" %>
      <html>
      <head runat="server">
      <title>Login Page</title>
      </head>
      <body>
         <form id="form1" runat="server">
            <asp:Login id="Login1" runat="server"
                  BorderStyle="Solid"
                  BackColor="#ffffcc"
                  BorderWidth="1px"
                  BorderColor="#cccc99"
                  Font-Size="10pt"
                  Font-Names="Verdana">
               <TitleTextStyle Font-Bold="True"
                  ForeColor="#ffffff"
                  BackColor="#666666"/>
            </asp:Login>
         </form>
      </body>
      </html>
      
    • Speichern Sie den Code als „Login.aspx“ im Stammverzeichnis Ihrer Website.

  3. Erstellen Sie eine „Web.config“-Datei für Ihre Website:

    • Fügen Sie den folgenden Code in einem Text-Editor ein:

      <configuration>
         <system.web>
            <!-- Add the read-only XML membership provider and set it as the default. -->
            <membership defaultProvider="AspNetReadOnlyXmlMembershipProvider">
               <providers>
                  <add name="AspNetReadOnlyXmlMembershipProvider"
                     type="ReadOnlyXmlMembershipProvider, ReadOnlyXmlMembershipProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=91454274822e8111"
                     description="Read-only XML membership provider"
                     xmlFileName="~/App_Data/Users.xml" />
               </providers>
            </membership>
            <!-- Add the read-only XML role provider and set it as the default. -->
            <roleManager enabled="true" defaultProvider="AspNetReadOnlyXmlRoleProvider">
               <providers>
                  <add name="AspNetReadOnlyXmlRoleProvider"
                     type="ReadOnlyXmlRoleProvider, ReadOnlyXmlRoleProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a9c0f8ad39898a3c"
                     description="Read-only XML role provider"
                     xmlFileName="~/App_Data/Users.xml" />
               </providers>
            </roleManager>
            <!-- Set the authentication mode to forms authentication. -->
            <authentication mode="Forms" />
         </system.web>
         <system.webServer>
            <!-- Configure the authentication and roles modules for all content. -->
            <modules>
               <remove name="RoleManager" />
               <remove name="DefaultAuthentication" />
               <remove name="FormsAuthentication" />
               <add name="FormsAuthentication"
                  type="System.Web.Security.FormsAuthenticationModule"
                  preCondition="" />
               <add name="DefaultAuthentication"
                  type="System.Web.Security.DefaultAuthenticationModule"
                  preCondition="" />
               <add name="RoleManager"
                  type="System.Web.Security.RoleManagerModule"
                  preCondition="" />
            </modules>
            <!-- Add authorization rules for membership roles. -->
            <security>
               <authorization>
                  <clear />
                  <add accessType="Allow" roles="Administrators" />
                  <add accessType="Allow" roles="Members" />
               </authorization>
            </security>
         </system.webServer>
      </configuration>
      

      Hinweis

      Die „PublicKeyToken“-Werte in den Abschnitten <providers> Ihrer „web.config“-Datei müssen mit den „PublicKeyToken“-Werten im Abschnitt <trustedProviders> Ihrer „Administration.config“-Datei übereinstimmen.

    • Speichern Sie den Code als „Web.config“ im Stammverzeichnis Ihrer Website.

Zusammenfassung

In dieser exemplarischen Vorgehensweise haben Sie Folgendes ausgeführt:

  • Sie haben zwei Klassenprojekte in Visual Studio 2008 für die schreibgeschützten XML-Mitgliedschafts- und -Rollenanbieter eingerichtet.
  • Sie haben die Projekte kompiliert und sie zum globalen Assemblycache hinzugefügt.
  • Sie haben die XML-Mitgliedschafts- und -Rollenanbieter als vertrauenswürdige Anbieter für IIS hinzugefügt.
  • Sie haben eine Website für die Formularauthentifizierung mit den XML-Anbietern konfiguriert.