MSDN Magazin > Home > Ausgaben > 2008 > February >  Office Space: Sicherheitsprogrammierung in Shar...
Office Space
Sicherheitsprogrammierung in SharePoint 2007
Ted Pattison

Codedownload verfügbar unter: OfficeSpace2008_02.exe (209 KB)
Browse the Code Online
Die Grundlagen der Sicherheitsprogrammierung mit Windows®- und ASP.NET-Sicherheit sind Ihnen möglicherweise bereits bekannt, aber wie gut kennen Sie die zusätzliche Sicherheitsschicht von Windows SharePoint® Services 3.0 (WSS)? Im Office Space-Artikel dieses Monats werden neue Sicherheitsbegriffe und -konzepte vorgestellt, die mit WSS eingeführt werden. Außerdem erhalten Sie eine schnelle Einführung in die Welt der Sicherheitsprogrammierung mithilfe des WSS-Objektmodells.
Ich empfehle Ihnen, das Beispielprojekt zu diesem Artikel herunterzuladen und den Code mitzuverfolgen, der in diesem Artikel vorgestellt wird. Das Projekt wurde dafür konfiguriert, nach dem Erstellungsprozess eine Batchdatei auszuführen, die alle Projektkomponenten in ein WSS-Lösungspaket kompiliert, das dann in der lokalen WSS-Farm installiert wird. Wenn Sie das Projekt erstellt und die Lösung installiert haben, können Sie zu einer beliebigen Websitesammlung navigieren und das Feature namens „Security Demo“ aktivieren, das sich im Bereich der Websitesammlung befindet. Das Menü „Websiteaktionen“ ermöglicht Ihnen dann, zu benutzerdefinierten Anwendungsseiten zu navigieren, die über Code verfügen, anhand dessen WSS-Sicherheitsprogrammierverfahren demonstriert werden.

Externe Sicherheitsprinzipale und das SPUser-Objekt
Die meisten Sicherheitsmodelle basieren auf Sicherheitsprinzipalen. Jeder Sicherheitsprinzipal repräsentiert entweder einen Benutzer oder eine Gruppe. Benutzer verfügen über Konten, mit denen sie sich authentifizieren. Nach der Authentifizierung erhält jeder Benutzer eine Identität. Im Szenario, in dem ein Benutzer sich mit einem Windows-Konto authentifiziert hat, können Sie die Microsoft® .NET Framework-Sicherheitsklassen im System.Security-Namespace verwenden, um eine Identität abzurufen, die auf das spezifische Windows-Konto zurückverweist und Ihnen ermöglicht, den Anmeldenamen des Benutzers zu ermitteln:
WindowsIdentity identity = WindowsIdentity.GetCurrent();
string WindowsLogin = identity.Name;
Mittels WindowsIdentity können Sie dynamisch ein WindowsPrincipal erstellen, mit dem Sie testen können, ob der aktuelle Benutzer ein Mitglied einer Active Directory®-Gruppe oder lokalen Windows-Gruppe ist, und zwar etwa so:
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
if( principal.IsInRole(@"LITWAREINC\AllFTE") ){
  // perform operation allowed for fulltime employees
}
ASP.NET unterstützt sowohl Windows-Authentifizierung als auch formularbasierte Authentifizierung (Forms Based Authentication, FBA). Das User-Objekt in ASP.NET eliminiert die Abhängigkeit von Windows-Konten, indem es das User-Objekt auf der IPrincipal-Schnittstelle statt der WindowsPrincipal-Klasse modelliert. Die ASP.NET-Laufzeit erstellt dynamisch verschiedene Arten von IPrincipal-Objekten, die davon abhängen, ob sich der aktuelle Benutzer mithilfe eines Windows-Kontos oder eines FBA-Kontos authentifiziert hat:
IPrincipal AspUser = HttpContext.Current.User;
string AspUserName = AspUser.Identity.Name;
Das ASP.NET-User-Objekt bietet auch eine Möglichkeit, mithilfe der IsInRole-Methode zu prüfen, ob ein Benutzer einer bestimmten Rolle angehört. Bei Windows-Benutzern zeigt die IsInRole-Methode Ihnen, ob der aktuelle Benutzer Mitglied einer Active Directory-Gruppe ist. Wenn Sie FBA-Konten zusammen mit einem ASP.NET-Rollenanbieter verwenden, können Sie mithilfe der IsInRole-Methode auch prüfen, ob der FBA-Benutzer einer spezifischen ASP.NET-Rolle hinzugefügt wurde:
IPrincipal AspUser = HttpContext.Current.User;
if(AspUser.IsInRole("Site Administrators") {
  // perform privileged operation
}
Durch den Vorgang der Authentifizierung wird eine Art Beleg erzeugt, der vom System zur Laufzeit verwendet wird, um eine Benutzeridentität zu repräsentieren und Mitgliedschaft in Gruppen oder Rollen nachzuverfolgen. Wenn sich ein Benutzer mit einem Windows-Konto authentifiziert, ist der Authentifizierungsbeleg ein Windows-Sicherheitstoken. Wenn sich der Benutzer mit einem FBA-Konto authentifiziert, ist der Authentifizierungsbeleg ein HTTP-Cookie, das von der ASP.NET-Laufzeit und einem spezifischen Authentifizierungsanbieter erstellt wird.
Machen Sie sich bewusst, dass WSS keine Unterstützung für das Authentifizieren von Benutzern bietet. Stattdessen verwendet WSS zugrunde liegende Authentifizierungskomponenten, die von verschiedenen ASP.NET-Authentifizierungsanbietern bereitgestellt werden. Der Beitrag, den WSS beim Sichern einer Website leistet, hängt mit dem Konfigurieren der Autorisierung und der Zugriffssteuerung zusammen. WSS ermöglicht es, im Bereich einer Websitesammlung externe Sicherheitsprinzipale wie Windows-Benutzer, FBA-Benutzer, Windows-Gruppen und ASP.NET-Rollen nachzuverfolgen. Mit WSS können Sie auch die Berechtigungen konfigurieren, die diesen externen Prinzipalen zugewiesen sind und Benutzern erlauben, auf sicherungsfähige WSS-Objekte zuzugreifen, z. B. Websites, Listen, Elemente und Dokumente.
Beachten Sie, dass die Websitesammlung eine bedeutende Rolle beim Konfigurieren der Autorisierung und Zugriffssteuerung spielt. WSS betrachtet jede Websitesammlung gewissermaßen als separaten Bereich, was das Nachverfolgen externer Prinzipale und das Konfigurieren von Berechtigungen betrifft. Durch den allgemeinen Entwurf von WSS wird jede Websitesammlung absichtlich isoliert, damit die Sicherheitseinstellungen eines Benutzers in einer Websitesammlung sich nicht auf Berechtigungen oder Zugriffssteuerungsrichtlinien in einer anderen Websitesammlung auswirken.
Das WSS-Objektmodell repräsentiert externe Sicherheitsprinzipale mithilfe von SPUser-Objekten. Sie können das SPUser-Objekt für den aktuellen Benutzer über das aktuelle SPWeb-Objekt abrufen:
SPWeb site = SPContext.Current.Web;
SPUser user = site.CurrentUser;
string DisplayName = user.Name;
string Login = user.LoginName;
string EMail = user.Email;
string User Notes = user.Notes;
Das SPUser-Objekt macht Eigenschaften eines externen Sicherheitsprinzipals verfügbar, z. B. Anmeldename, Anzeigename und E-Mail-Adresse. Diese Eigenschaften werden normalerweise von einem zugrunde liegenden Benutzerrepository, wie einer Active Directory-Domäne, abgerufen, wenn der externe Prinzipal einer Website hinzugefügt wird. Das SPUser-Objekt macht auch Eigenschaften verfügbar, die WSS-spezifische Metadaten nachverfolgen, z. B. das Feld „Notizen“.
WSS behält die Profildaten für externe Benutzer, Gruppen und Rollen in einer ausgeblendeten Liste bei, die Benutzerinformationsliste genannt wird. Jedes Mal, wenn WSS eine neue Websitesammlung bereitstellt, wird automatisch die Benutzerinformationsliste als ausgeblendete Liste auf der Website oberster Ebene erstellt. WSS fügt dann ein neues Profil für jeden externen Prinzipal hinzu, wenn dem entsprechenden Prinzipal das erste Mal Berechtigungen zugewiesen werden oder wenn er das erste Mal eine Sicherheitsüberprüfung für den Zugriff auf ein sicherungsfähiges Objekt besteht. Beachten Sie, dass sich das in der Benutzerinformationsliste gespeicherte Benutzerprofil nicht über Websitesammlungen erstreckt. Wenn Benutzer ihre Profileinstellungen in einer Websitesammlung aktualisieren, erfolgt keine Änderung der Profileinstellungen dieses Benutzers in anderen Websitesammlungen.
Eine andere potenzielle Quelle für Verwirrung besteht darin, dass SPUser-Objekte nicht immer tatsächliche Benutzer repräsentieren. SPUser-Objekte können auch Active Directory-Gruppen und ASP.NET-Rollen repräsentieren. WSS verfolgt ein Profil für jeden dieser externen Prinzipaltypen in der Benutzerinformationsliste nach, zusammen mit den Profildaten für externe Benutzer.
Viele der programmgesteuerten Aspekte des SharePoint-Sicherheitsmodells werden auf der Websiteebene durch SPWeb-Objekte verfügbar gemacht. Dies ist der Fall, wenn Sie feststellen möchten, welche Benutzer Mitglieder der aktuellen Website sind. Ein SPWeb-Objekt macht drei verschiedene Sammlungen von Benutzern verfügbar, wie in diesem Codefragment gezeigt:
SPWeb site = SPContext.Current.Web;
SPUserCollection c1 = site.Users;
SPUserCollection c2 = site.AllUsers;
SPUserCollection c3 = site.SiteUsers;
Die Users-Sammlung hat unter diesen drei Sammlungen die geringste Mitgliederzahl. Diese Sammlung umfasst alle externen Prinzipale, denen explizit Berechtigungen innerhalb der aktuellen Website zugewiesen wurden.
Die AllUsers-Sammlung umfasst alle Mitglieder der Users-Sammlung sowie externe Benutzer, die mithilfe impliziter Berechtigungen, die aufgrund einer Gruppen- oder Rollenmitgliedschaft verfügbar sind, auf Objekte innerhalb der Website zugegriffen haben. Stellen Sie sich zum Beispiel einen Benutzer namens Brian vor, dessen Anmeldename „LITWAREINC\BrianC“ lautet und dem nie explizite Berechtigungen dafür erteilt wurden, auf eine Website zuzugreifen und eine bestimmte Liste anzuzeigen. Er kann aber aufgrund seiner Mitgliedschaft in einer Active Directory-Gruppe, die mit Listenanzeigeberechtigungen konfiguriert wurde, möglicherweise trotzdem auf die Liste zugreifen. Wenn Brian das erste Mal auf die Website oder eines ihrer Objekte zugreift (z. B. mithilfe impliziter Berechtigungen auf eine Liste), wird er als Mitglied der AllUsers-Sammlung, aber nicht als Mitglied der Users-Sammlung hinzugefügt.
Die SiteUsers-Sammlung ist eine Aggregation, die die Mitgliedschaft für jede AllUsers-Sammlung innerhalb der aktuellen Websitesammlung kombiniert. Die Mitgliedschaft in dieser Sammlung umfasst alle externen Prinzipale, denen Berechtigungen für beliebige Objekte innerhalb der Websitesammlung zugewiesen wurden, sowie alle externen Benutzer, denen mittels impliziter Berechtigungen Zugriff auf beliebige Objekte der Websitesammlung gewährt wurde.

Hinzufügen authentifizierter und externer Benutzer
Wie wird also ein neues WSS-Benutzerprofil für einen Benutzer erstellt, der sich mit einem Active Directory-Konto authentifiziert hat? Wenn Sie eine benutzerdefinierte Benutzeroberflächenkomponente erstellen müssen, die Standardbenutzern oder dem Besitzer der Websitesammlung ermöglicht, einen Benutzer oder eine Gruppe aus einer Active Directory-Domäne auszuwählen, sollten Sie lernen, wie das PeoplePicker-Steuerelement verwendet wird (siehe Abbildung 1). Es handelt sich um einen sehr praktischen, wiederverwendbaren Steuerelementtyp, der in WSS enthalten ist. Sie können dieses Steuerelement einer benutzerdefinierten Anwendungsseite oder einem User-Steuerelement hinzufügen. Dazu benötigen Sie ein Steuerelementtag ähnlich dem folgenden:
Abbildung 1 PeoplePicker-Steuerelement (Klicken Sie zum Vergrößern auf das Bild)
<SharePoint:PeopleEditor 
       ID="pickerPrincipal" 
       AllowEmpty="false" 
       ValidatorEnabled="true"
       MultiSelect="false" 
       SelectionSet="User, SecGroup, DL" 
       Width="280px"
       runat="server"   />
In diesem Beispiel wurde das PeoplePicker-Steuerelement durch Zuweisen der SelectSet-Eigenschaft mit den Werten „User“, „SecGroup“ und „DL“ konfiguriert. Durch diese SelectSet-Einstellungen wird das Steuerelement konfiguriert, um dem Benutzer zu ermöglichen, einen Benutzer, eine Gruppe oder eine Verteilerliste mit Active Directory auszuwählen und aufzulösen.
Sie können auf die PeoplePicker-Steuerelementeigenschaften programmgesteuert zugreifen, um die zugeordneten Anmeldekontonamen für die zugrunde liegenden Konten abzurufen, nachdem der Benutzer mit dem Steuerelement einen oder mehrere Sicherheitsprinzipale ausgewählt hat. Dann können Sie den Code bereitstellen, der diese Prinzipale als Websitemitglieder hinzufügt und ihre Zugriffsrechte konfiguriert.
Als Nächstes sollen Sie erfahren, wie ein externer Benutzer oder eine externe Gruppe als Websitemitglied hinzugefügt wird. Nach einem kurzen Blick auf das WSS-Objektmodell denken Sie möglicherweise, dass Sie externe Sicherheitsprinzipale einfach direkt einer der SPUser-Sammlungen hinzufügen sollten, z. B. SiteUsers:
SPWeb site = SPContext.Current.Web;

site.SiteUsers.Add(@"LITWAREINC\BrianC",
                    "brianc@litwareinc.com",
                    "Brian Cox",
                    "Notes about Brian Cox");

site.SiteUsers.Add(@"LITWAREINC\AllFTE",
                    "allFTE@litwareinc.com",
                    "All Full-time Employees",
                    "Notes about FTE DL");
Obwohl durch diesen Ansatz in der Benutzerinformationsliste für einen externen Prinzipal ein Profil erstellt wird, wirkt sich dies nur wenig auf die Sicherheit aus, da hierdurch keine Berechtigungen zugewiesen werden. Eine bessere Möglichkeit für das Hinzufügen eines neuen externen Sicherheitsprinzipals ist das Zuweisen von Berechtigungen, die Benutzern innerhalb der aktuellen Website Zugriff gewähren. Sie müssen jedoch zuerst lernen, wie Berechtigungsebenen erstellt und zugewiesen werden.

Arbeiten mit Berechtigungsebenen
Eine Berechtigungsebene ist ein benannter Satz von Berechtigungen, der im Bereich einer Website definiert ist. WSS umfasst vier integrierte Berechtigungsebenen: Lesen, Teilnehmen, Entwerfen und vollständiger Zugriff. Wenn Sie größere Granularität benötigen, können Sie mithilfe des WSS-Objektmodells oder über die Standard-WSS-Administrationsseiten, auf die der Besitzer der Websitesammlung zugreifen kann, Ihre eigenen benutzerdefinierten Berechtigungsebenen erstellen.
Berechtigungsebenen werden manchmal Rollen genannt und werden im WSS-Objektmodell mithilfe von SPRoleDefinition-Objekten repräsentiert. Sie können einem externen Benutzer oder Gruppen mithilfe eines SPRoleAssignment-Objekts eine Berechtigungsebene zuweisen. Hier wird die integrierte Teilnehmen-Berechtigungsebene zum Beispiel dem Windows-Benutzer mit dem Anmeldenamen „LITWAREINC\BrianC“ zugewiesen:
SPWeb site = SPContext.Current.Web;
SPRoleDefinition role = site.RoleDefinitions["Contribute"];
SPRoleAssignment roleAssignment;
roleAssignment = new SPRoleAssignment(@"LITWAREINC\BrianC",
                                       "brianc@litwareinc.com",
                                       "Brian Cox",
                                       "Notes about Brian Cox");

roleAssignment.RoleDefinitionBindings.Add(role);
site.RoleAssignments.Add(roleAssignment);
Dieses Verfahren macht es unnötig, den Benutzer einer der SPUser-Sammlungen hinzuzufügen, da WSS dies automatisch erledigt, wenn einem externen Benutzer oder einer externen Gruppe zum ersten Mal eine Berechtigung innerhalb einer Website zugewiesen wird. Der Code, den Sie gerade gesehen haben, erstellt in der Benutzerinformationsliste ein Benutzerprofil, wenn keines vorhanden ist, und fügt den Benutzer der Users-Sammlung der aktuellen Website als Mitglied hinzu.

WSS-Gruppen
Obwohl das WSS-Sicherheitsmodell externe Sicherheitsprinzipale als SPUser-Objekte repräsentiert, stellt es auch WSS-Gruppen als Mittel zur Vereinfachung der Konfiguration von Berechtigungen innerhalb des Bereichs einer Websitesammlung bereit. Sie können zum Beispiel innerhalb einer Websitesammlung für spezifische Benutzerrollen, z. B. Websitemitglieder, Inhaltsmanager und Websiteadministratoren, einen Satz von WSS-Gruppen entwerfen. Anschließend können Sie die Sicherheitseinstellungen der Website konfigurieren, indem Sie Berechtigungsebenen einfach WSS-Gruppen zuweisen statt sie direkt SPUser-Objekten zuzuweisen.
Der offensichtliche Vorteil des Erstellens von WSS-Gruppen besteht darin, dass sich mit ihrer Hilfe die Notwendigkeit der Neukonfiguration von Berechtigungen beseitigen lässt, wenn externe Benutzer und Gruppen neu hinzugefügt oder entfernt werden. Es genügt, wenn Sie die Berechtigungen einmal ganz zu Anfang konfigurieren, wenn die Website erstellt wird. Später fügen Sie den WSS-Gruppen einfach externe Benutzer und Gruppen hinzu bzw. entfernen sie aus diesen. WSS-Gruppen folgen genau den gleichen Entwurfsprinzipien wie Active Directory-Gruppen. Der Hauptunterschied besteht darin, dass WSS-Gruppen nur innerhalb des Bereichs einer einzelnen Websitesammlung definiert und verfügbar sind.
WSS-Gruppen sind im WSS-Objektmodell als SPGroup-Objekte repräsentiert. Das SPWeb-Objekt stellt zwei Sammlungen von SPGroup-Objekten namens „Groups“ und „SiteGroups“ bereit. Die Groups-Sammlung umfasst sämtliche WSS-Gruppen, denen direkt Berechtigungen in der aktuellen Website zugewiesen wurden, während die SiteGroups-Sammlung eine Obermenge der Groups-Sammlung ist und alle WSS-Gruppen umfasst, die innerhalb der aktuellen Websitesammlung erstellt wurden.
Wenn Sie eine neue WSS-Gruppe erstellen möchten, sollten Sie die Add-Methode aufrufen, die durch die SiteGroups-Sammlung verfügbar gemacht wird, und dann die neue WSS-Gruppe mit einer oder mehreren Berechtigungsebenen innerhalb einer Zielwebsite zuweisen. Abbildung 2 zeigt ein Beispiel für das Erstellen einer neuen WSS-Gruppe namens „Site Members“ und das Zuweisen der integrierten Berechtigungsebene „Teilnehmen“ zu dieser Gruppe innerhalb der aktuellen Website.
SPWeb site = SPContext.Current.Web;
SPUser currentUser = site.CurrentUser;

// create new group
site.SiteGroups.Add("Site Members", currentUser, currentUser,
                     "Site Group created at " + DateTime.Now.ToString());

// assign permission level to new group
SPGroup NewGroup = site.SiteGroups["Site Members"];
SPRoleAssignment roleAssignment = new SPRoleAssignment(NewGroup);
SPRoleDefinition permLevel = site.RoleDefinitions["Contribute"];
roleAssignment.RoleDefinitionBindings.Add(permLevel);
site.RoleAssignments.Add(roleAssignment);

Wenn Sie eine neue WSS-Gruppe erstellt haben, ist es ziemlich leicht, externe Benutzer und Gruppen als Mitglieder hinzuzufügen. Ein SPGroup-Objekt macht eine AddUser-Methode verfügbar, die ein SPUser-Objekt akzeptiert, das Ihnen ermöglicht, externe Benutzer und Gruppen hinzuzufügen:
SPWeb site = SPContext.Current.Web;
SPUser currentUser = site.CurrentUser;
SPGroup group = site.SiteGroups["Site Members"];
SPUser user1 = site.SiteUsers[@"LITWAREINC\BrianC"];
SPUser user2 = site.SiteUsers[@"LITWAREINC\AllFTE"];
group.AddUser(user1);
group.AddUser(user2);

Identität, Erhöhung und Identitätswechsel
Der Arbeitsprozess für eine WSS-Webanwendung wird durch IIS-Anwendungspools gesteuert. Die Arbeitsprozessidentität für eine Webanwendung ist über die Anwendung „SharePoint-Zentraladministration“ konfigurierbar. Sie sollten die Arbeitsprozessidentität für eine Webanwendung mit Domänenkonten (z. B. LITWAREINC\SP_WorkerProcess) konfigurieren, statt sich auf lokale Konten (wie NETZWERKDIENST) zu verlassen.
Beachten Sie, dass die Arbeitsprozessidentität für eine Webanwendung ein privilegiertes Windows-Konto sein muss, das mit SQL Server-Berechtigungen für das Lesen und Schreiben in einer oder mehr Inhaltsdatenbanken konfiguriert wurde. Die Arbeitsprozessidentität für die Webanwendung, die die SharePoint-Zentraladministrations-Website ausführt, muss sogar noch privilegierter sein, da sie Lese- und Schreibberechtigungen für die Konfigurationsdatenbank der Farm erfordert.
Wenn der Code hinter einem Webpart oder einer benutzerdefinierten Anwendungsseite in Antwort auf eine Benutzeranforderung ausgeführt wird, wird er nicht mit der Arbeitsprozessidentität der hostenden Webanwendung ausgeführt. Stattdessen verwendet WSS Identitätswechsel, um ein anderes Windows-Konto für den Windows-Sicherheitskontext zu verwenden. Wenn Sie innerhalb der web.config-Datei nach einer WSS-Webanwendung suchen, sehen Sie den folgenden Eintrag:
<configuration>
  <system.web>
    <identity impersonate="true" />
  </system.web>
</configuration>
Wenn eine Anforderung für einen Benutzer ausgeführt wird, der sich mit einem Windows-Konto authentifiziert hat, verwendet die Anforderung die Windows-Identität des aktuellen Benutzers. Dieser Ansatz funktioniert jedoch nicht für FBA-Benutzer, weil die FBA-Authentifizierung kein Windows-Sicherheitstoken erstellt und über keine Windows-Identität verfügt. Deshalb verwenden Anforderungen für Benutzer, die unter FBA-Authentifizierung ausgeführt werden, die Identität des Windows-Kontos, das für anonymen Zugriff konfiguriert wurde. Die Standardzuweisung für dieses Konto in IIS ist das IUSER_MACHINENAME-Konto, aber Sie können dies (und sollten es in der Regel) neu konfigurieren, damit auf ein Domänenkonto gezeigt wird.
Nun ist es an der Zeit, die WSS-Sicherheitsprogrammierung auf einer höheren Ebene zu betrachten. Das WSS-Sicherheitsmodell zwingt Entwickler oft, zwischen Windows-Identität und WSS-Benutzeridentität zu unterscheiden. Dies ist innerhalb einer Anforderung, in der sowohl die aktuelle Windows-Identität als auch die aktuelle WSS-Benutzeridentität auf die gleiche Windows-Anmeldung zeigen, möglicherweise nicht so offensichtlich. In Szenarios, die FBA verwenden, ist die Sache jedoch etwas komplizierter. Zum Beispiel könnte die WSS-Benutzeridentität auf einen FBA-Benutzer namens Andrew zeigen, während die zugrunde liegende Windows-Identität auf dem IUSER_MACHINENAME-Konto basiert. Wenn Ihr Code versucht, auf WSS-Objekte zuzugreifen, führt WSS mithilfe der WSS-Identität des Benutzers Zugriffsüberprüfungen aus. Wenn Ihr Code versucht, auf externe Objekte außerhalb von WSS zuzugreifen, z. B. Dateien, die vom Windows-Betriebssystem verwaltet werden, führt das Betriebssystem Zugriffsüberprüfungen mithilfe der Windows-Identität aus, unter der der Code gerade ausgeführt wird.
Es gibt Situationen, in denen Ihr Code mit mehr Berechtigungen ausgeführt werden muss, als dem aktuellen Benutzer zur Verfügung stehen. Stellen Sie sich zum Beispiel ein Szenario vor, in dem Ihr Code Daten in eine Liste schreiben muss, wenn er eine Anforderung für einen Benutzer verarbeitet, der lediglich über Leseberechtigungen verfügt. Standardmäßig wird Ihr Code mit den gleichen Berechtigungen ausgeführt, die dem aktuellen Benutzer zur Verfügung stehen. Sie können jedoch die RunWithElevatedPrivileges-Methode der SPSecurity-Klasse aufrufen, um den Sicherheitskontext Ihres Codes zu erhöhen. Beachten Sie, dass ein Aufruf an RunWithElevatedPrivileges sowohl die WSS-Benutzeridentität als auch die Windows-Identität erhöht.
Stellen Sie sich jetzt ein Szenario vor, in dem sich ein Benutzer mit einem Windows-Konto mit dem Anmeldenamen „LITWAREINC\BrianC“ authentifiziert hat. Durch einen Aufruf an RunWithElevatedPrivileges wird die WSS-Benutzeridentität auf das SHAREPOINT\System-Konto erhöht. Das SHAREPOINT\System-Konto ist in die WSS-Laufzeit integriert und verfügt innerhalb des WSS-Autorisierungsmodells über uneingeschränkte Berechtigungen. Durch einen Aufruf an RunWithElevatedPrivileges wird auch die Windows-Identität des ausführenden Codes gewechselt, sodass er mit der Arbeitsprozessidentität der aktuellen Webanwendung ausgeführt wird:
// BEFORE ELEVATION
// WSS User identity = LITWAREINC\BrianC
// Windows identity = LITWAREINC\BrianC

SPSecurity.RunWithElevatedPrivileges(delegate() {
  // AFTER ELEVATION
  // WSS User identity = SHAREPOINT\System
  // Windows identity = LITWAREINC\SP_WorkerProcess
});
In einigen Szenarios werden Sie vielleicht die RunWithElevatedPrivileges-Methode aufrufen, um die Windows-Identität des aktuellen Aufrufs zu ändern, bevor Sie versuchen, auf eine Datei innerhalb des Windows-Dateisystems oder innerhalb einer SQL Server-Datenbank zuzugreifen. Beachten Sie auch, dass der Wechsel von der Windows-Identität zu einer Prozessidentität wie LITWAREINC\SP_WorkerProcess möglicherweise die Notwendigkeit beseitigt, Delegierung innerhalb einer Active Directory-Umgebung zu konfigurieren. Dies kann sehr nützlich sein, wenn Sie über benutzerdefinierte Webparts verfügen, die mithilfe der in Windows integrierten Authentifizierung in einer SQL Server-Remotedatenbank auf Daten zugreifen.
Außerdem gibt es Szenarios, in denen Sie vielleicht die RunWithElevatedPrivileges-Methode aufrufen möchten, um die WSS-Benutzeridentität auf SHAREPOINT\System zu erhöhen, damit Ihr Code Vorgänge ausführen kann, die dem aktuellen Benutzer erlaubt sind. Sobald Ihr Code als SHAREPOINT\System ausgeführt wird, können Sie innerhalb des WSS-Autorisierungssubsystems fast alles tun, was Sie möchten.
Es gibt eine Schwierigkeit, wenn Sie RunWithElevatedPrivileges aufrufen, um eine Erhöhung auf das SHAREPOINT\System-Konto zu erreichen. Stellen Sie sich zum Beispiel vor, dass Sie RunWithElevatedPrivileges aufrufen und dann versuchen, über die SPContext.Current-Eigenschaft in der aktuellen Websitesammlung oder Website auf Objekte zuzugreifen. Sie erwarten wahrscheinlich nicht, dass Ihr Code fehlschlägt, aber es könnte passieren:
SPSecurity.RunWithElevatedPrivileges(delegate() {
  SPSite siteCollection = SPContext.Current.Site;
  // next line fails if current user is Contributor
  string siteCollectionOwner = siteCollection.Owner;
});
Weshalb schlägt dieser Beispielcode fehl, nachdem Sie die WSS-Benutzeridentität auf SHAREPOINT\System erhöht haben? Dies hängt mit dem Zeitpunkt der Erstellung des SPSite-Objekts zusammen. Die gültigen Berechtigungen für ein SPSite-Objekt und seine untergeordneten SPWeb-Objekte hängen nicht von der aktuellen WSS-Benutzeridentität ab. Stattdessen hängen die Berechtigungen von der WSS-Benutzeridentität zum Zeitpunkt der Erstellung des SPSite-Objekts ab. Hier wurde das SPSite-Objekt, das über SPContext.Current zugänglich ist, früher in der Anforderung erstellt, und zwar bevor Ihr Code die Möglichkeit hatte, seine WSS-Benutzeridentität zu ändern.
Folglich erfordert das Verfahren, das Sie verwenden sollten, dass Sie ein neues SPSite-Objekt erstellen, nachdem Sie RunWithElevatedPrivileges aufgerufen und die WSS-Benutzeridentität auf SHAREPOINT\System erhöht haben:
SPSecurity.RunWithElevatedPrivileges(delegate() {
  using (SPSite elevatedSiteCollection = new SPSite(this.Site.ID)) {
    using (SPWeb elevatedSite =
      elevatedSiteCollection.OpenWeb(this.Web.ID)) {
      // access elevatedSiteCollection and 
      //elevatedSite as SHAREPOINT\System
    }
  }
});
Dies ermöglicht es, eine Websitesammlung und die darin enthaltenen Websites zu öffnen, sodass Ihr Code als SHAREPOINT\System auf Objekte zugreifen kann.
Möglicherweise müssen Sie eine spezifische WSS-Benutzeridentität verwenden. Dies ist oft der Fall, wenn der Code für einen Ereignishandler oder eine benutzerdefinierte Workflowvorlage geschrieben wird, wobei der Code standardmäßig als SHAREPOINT\System ausgeführt wird. Zum Beispiel möchten Sie vielleicht eine spezifische WSS-Benutzeridentität verwenden, bevor Sie ein neues Objekt erstellen, damit der WSS-Benutzer als Besitzer des neuen Objekts anerkannt wird.
Um eine WSS-Benutzeridentität zu verwenden, müssen Sie zuerst ein SPUserToken-Objekt erstellen. Sie können dazu auf die UserToken-Eigenschaft eines SPUser-Objekts zugreifen. Sobald Sie über das SPUserToken-Objekt verfügen, können Sie es dazu verwenden, mithilfe einer überladenen Version des SPSite-Klassenkonstruktors ein neues SPSite-Objekt zu erstellen. Dieses Verfahren wird in Abbildung 3 gezeigt.
SPWeb siteCollection = SPContext.Current.Site;
SPWeb site = SPContext.Current.Web;

// get SPUser object and acquire token
SPUser targetUser = site.SiteUsers[@"LITWAREINC\BrianC"];
SPUserToken token = targetUser.UserToken;

// create new SPSite and SPWeb object to impersonate user
using (SPSite impersonatedSiteCollection = 
              new SPSite(siteCollection.ID, token)) {
  using (SPWeb impersonatedSite = 
               impersonatedSiteCollection.OpenWeb(site.ID)) {
    // WSS identity switched to impersonate BrianC
    // Windows identity does not change
  }
}

Es gibt einige wichtige Punkte beim WSS-Benutzeridentitätswechsel, auf die hingewiesen werden sollte. Zum einen unterscheidet sich das Verwenden einer WSS-Benutzeridentität von einem Aufruf an RunWithElevatedPrivileges, weil es die aktuelle Windows-Identität nicht ändert. Wenn eine Anforderung zum Beispiel unter der Windows-Identität von LITWAREINC\SP_WorkerProcess ausgeführt wird, bevor Sie eine WSS-Benutzeridentität verwenden, wird der Code weiterhin unter der gleichen Windows-Identität ausgeführt. Durch einen WSS-Benutzeridentitätswechsel wird die aktuelle Windows-Identität nicht in die Identität des entsprechenden Benutzers geändert.
Es ist auch wichtig, darauf hinzuweisen, dass Code in einem privilegierten Zustand ausgeführt werden muss, um die Identität eines anderen Benutzers zu verwenden. In einem Ereignishandler oder einer benutzerdefinierten Workflowvorlage müssen Sie sich darüber keine Gedanken machen, da der Code standardmäßig als SHAREPOINT\System ausgeführt wird. Code innerhalb eines Webparts oder hinter einer benutzerdefinierten Anwendungsseite muss jedoch u. U. RunWithElevatedPrivileges aufrufen, bevor er auch nur in der Lage ist, eine andere WSS-Benutzeridentität zu verwenden.

Sicherungsfähige Objekte
Die besondere Stärke des Konfigurierens der WSS-Sicherheit liegt in der Flexibilität, die von sicherungsfähigen Objekten wie Websites, Listen und Listenelementen geboten wird. Jedes sicherungsfähige Objekt kann eine Zugriffssteuerungsliste (Access Control List, ACL) enthalten, bei der es sich um eine binäre Datenstruktur handelt, die WSS zur Laufzeit verwendet, um zu bestimmen, ob einem Sicherheitsprinzipal Zugriff gewährt wurde. Standardmäßig ist das einzige sicherungsfähige Objekt mit einer ACL die Website oberster Ebene. Alle untergeordneten Objekte (wie Listen, Listenelemente und untergeordnete Websites) erben die ACL von ihrem übergeordneten Element, es sei denn, sie verhindern die Vererbung und stellen dadurch eine eigene spezielle ACL bereit.
Das WSS-Objektmodell enthält eine Schnittstelle namens „ISecurableObject“, die ein sicherungsfähiges Objekt innerhalb einer WSS-Websitesammlung modelliert (siehe Abbildung 4). Die ISecurableObject-Schnittstelle, die von SPWeb-, SPList- und SPItem-Objekten implementiert wird, bietet eine Grundlage für das Durchführen von Zugriffsüberprüfungen zur Laufzeit sowie für das Konfigurieren von Berechtigungen.
Abbildung 4 Die ISecurableObject-Schnittstelle (Klicken Sie zum Vergrößern auf das Bild)
Wenn Sie beginnen, Berechtigungen innerhalb einer Websitesammlung zu konfigurieren, sollten Sie sich bewusst sein, dass alle Websites, Listen und Listenelemente eine einzige Hierarchie sicherungsfähiger Objekte darstellen. Standardmäßig enthält nur die Website oberster Ebene eine spezielle ACL und definiert die Zuweisung von Berechtigungsebenen, durch die festgelegt wird, über welche Berechtigungen Benutzer für den Zugriff auf Objekte verfügen. Alle untergeordneten Objekte erben ihre Berechtigungen von der Website oberster Ebene. Sie können beim Konfigurieren der Zugriffssteuerung jedoch detaillierter vorgehen, indem Sie einem sicherungsfähigen Objekt einen eigenen speziellen Satz zugewiesener Berechtigungsebenen geben. Zum Beispiel ermöglicht Ihnen der Code in Abbildung 5, eine neue Dokumentbibliothek zu erstellen und mit einem speziellen Satz von Berechtigungen zu konfigurieren.
SPWeb site = SPContext.Current.Web;
Guid listID = site.Lists.Add("Proposals", 
                            "Library desc", 
                            SPListTemplateType.DocumentLibrary);

SPDocumentLibrary doclib = (SPDocumentLibrary)site.Lists[ListID];
doclib.OnQuickLaunch = true;
doclib.BreakRoleInheritance(false);
SPUser AllFteGroup = Web.SiteUsers[@"LITWAREINC\AllFTE"];
SPRoleAssignment assignAllFteGroup = new SPRoleAssignment(AllFteGroup);
SPRoleDefinition roleDesign = this.Web.RoleDefinitions["Read"];
assignAllFteGroup.RoleDefinitionBindings.Add(roleDesign);
doclib.RoleAssignments.Add(assignAllFteGroup);
doclib.Update();

Dieser Beispielcode unterbindet die Standardberechtigungsvererbung vom übergeordneten Element mithilfe eines Aufrufs an BreakRoleInheritance. Wenn Sie BreakRoleInheritance aufrufen und den Parameterwert „true“ übergeben, ist das sicherungsfähige Objekt anfänglich mit einer ACL konfiguriert, die eine Kopie der ACL des übergeordneten Objekts ist. Wenn Sie BreakRoleInheritance aufrufen und den Parameterwert „false“ übergeben, ist das sicherungsfähige Objekt anfänglich mit einer leeren ACL konfiguriert. Das bedeutet, dass diese Dokumentbibliothek keinen Zugriff für Benutzer bietet, die weder Besitzer noch Websiteadministratoren sind.
Mit Windows SharePoint Services 3.0 wurde eine willkommene Sicherheitsverbesserung hinzugefügt, die Ihnen das Konfigurieren von Berechtigungen bis hinunter zur Ebene von Elementen oder Dokumenten erlaubt. Dies wird durch das WSS-Objektmodell ermöglicht, da SPListItem-Objekte auch die ISecurableObject-Schnittstelle implementieren.
Der Code in Abbildung 6 erstellt ein neues Dokument innerhalb einer Dokumentbibliothek und konfiguriert es anschließend mit einem speziellen Satz von Berechtigungen, der von seiner übergeordneten Dokumentbibliothek abweicht. Beachten Sie, dass dieser Code eine Dienstprogrammmethode namens „WriteDocument“ verwendet, die einen SPDocumentLibrary-Verweis und einen Dateinamen akzeptiert. Die Methodenimplementierung verwendet die Office Open XML-Dateiformate, um ein Word-Dokument zu erstellen und es zurück in die Dokumentbibliothek zu schreiben. Die WriteDocument-Methode gibt einen SPFile-Verweis zurück, der zum Zugriff auf das mit dem Dokument verknüpfte SPListItem verwendet werden kann. Dies ermöglicht Ihnen, die Berechtigungsvererbung zu verhindern und einen speziellen Satz von Berechtigungen zuzuweisen.
SPWeb site = SPContext.Current.Web;
Guid listID = site.Lists.Add("Proposals",
                            "Library desc",
                            SPListTemplateType.DocumentLibrary);

SPDocumentLibrary doclib = (SPDocumentLibrary)Web.Lists[ListID];
doclib.OnQuickLaunch = true;
doclib.Update();
SPFile doc1 = WriteDocument(doclib, "Adventure Works Merger.docx");
doc1.Item.BreakRoleInheritance(false);
SPGroup group = Web.Groups["Litware Contact Managers"];
SPRoleAssignment assignContribute = new SPRoleAssignment(group);
SPRoleDefinition roleContibute = this.Web.RoleDefinitions["Contribute"];
assignContribute.RoleDefinitionBindings.Add(roleContibute);
doc1.Item.RoleAssignments.Add(assignContribute);
doc1.Item.Update();


Zusammenfassung
Zugegebenermaßen ist dieser Artikel eine etwas grobe Einführung in das komplexe Thema des WSS-Sicherheitsmodells. Es wurde aufgezeigt, wie WSS externe Sicherheitsprinzipale auf Ebene der Websitesammlung mit einem Profil innerhalb der Benutzerinformationsliste nachverfolgt, und wie WSS diese externen Sicherheitsprinzipale mithilfe von SPUser-Objekten im WSS-Objektmodell repräsentiert. Außerdem haben Sie erfahren, wie WSS Unterstützung für WSS-Gruppen bietet, und es wurden Ihnen einige Programmierverfahren für das Erhöhen von Berechtigungen und das Verwenden von WSS-Benutzeridentitäten vorgestellt. Diese Verfahren bieten die Leistungsfähigkeit und Flexibilität, die Sie beim Erstellen einer realen Anwendung benötigen.
Obwohl WSS für das Durchführen der Authentifizierung ein zugrunde liegendes System von Komponenten verwendet, übernimmt es selbst die Verantwortung für Autorisierung und Zugriffssteuerung. Das WSS-Autorisierungsmodell basiert größtenteils auf einem benannten Satz von Berechtigungen, die als Berechtigungsebenen oder Rollen bekannt sind. Eine Berechtigungsebene kann einem SPUser-Objekt zugewiesen werden, aber in der Praxis sollten Sie eher WSS-Gruppen Berechtigungsebenen zuweisen.

Senden Sie Fragen und Kommentare für Ted Pattison an mmoffice@microsoft.com.


Ted Pattison ist Autor, Schulungsleiter und SharePoint-MVP und lebt in Tampa, Florida, USA. Zusätzlich bietet er über sein Unternehmen Ted Pattison Group (www.TedPattison.net) Schulungen zu SharePoint für professionelle Entwickler an. Ted hat gerade sein Buch mit dem Titel „Inside Windows SharePoint Services 3.0“ für Microsoft Press fertig gestellt.

Page view tracker