\subsection{Spring Security}

Spring Security kann benutzt werden um Benutzer zu authentifizieren und für unterschiedliche Aktionen authorisieren. Dabei bietet das Framework viele Möglichkeiten wie Authentifizierung anhand normaler Benutzernamen und Passwörter, LDAP, OpenID, etc. an. Auch für Webapplikationen bietet es eine Fülle von Funktionalität wie Session Management, Remember Me Funktionalität etc.

\subsubsection{Mögliche Ebenen der Zugriffsbeschränkung}

Der Zugriff auf Seiten, Methoden oder Ressourcen kann dabei auf mehreren Ebenen geregelt werden. Die Spring Referenz \footnote{http://static.springsource.org/spring-security/site/docs/3.1.x/reference/el-access.html} beschreibt eine ausdrucksbasierte Zugriffskontrolle (Expression-Based Access Control) welche einen sehr feingranularen Zugriffsfilter bietet. Dabei kann man zum einen schon auf der Ebene von URLs erste Rechteprüfungen anstellen und den Zugriff auf diese Ressourcen komplett verwehren.

\begin{lstlisting}
<http use-expressions="true">
  <intercept-url pattern="/admin*"
    access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
    ...
</http>
\end{lstlisting}

Eine weitere Möglichkeit um Berechtigungen auf Methodenebene zu prüfen gibt es mit \lstinline~@Pre~ und \lstinline~@Post~ Annotationen. Dazu können mit Ausdrücken Regeln erstellt werden die erfüllt werden müssen um die Methode aufzurufen.

\begin{lstlisting}
@PreAuthorize("hasRole('ROLE_USER')")
public void create(Contact contact);
\end{lstlisting}

Es ist weiterhin sogar möglich, nicht nur ganze Methodenaufrufe zu filtern sondern anhand der übergebenen Objekte zu entscheiden, ob der aktuelle Benutzer die Rechte besitzt um dieses Objekt mit dieser Methode zu verarbeiten. Dabei kann nicht nur auf die Parameter zugegriffen werden sondern auch noch auf andere eingebaute Ausdrücke wie \lstinline~authentication~ welches Zugriff auf das Authentifizierungsobjekt des aktuellen Sicherheitskontexts bietet. Um innerhalb solcher Ausdrücke auf Parameter zugreifen zu können, muss der Code mit Debug-Informationen kompiliert werden.

\begin{lstlisting}
// Zugriff nur erlauben, wenn der angemeldete Benutzer admin-Rechte fuer das Contact-Objekt hat
@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);

// nur Zugriff auf Contact-Object des angemeldeten Benutzers erlauben
@PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact);
\end{lstlisting}

Mit \lstinline~PostFilter~ Ausdrücken können zurückgegebene Collections anhand der angegebenen Regeln gefiltert werden. Dabei sollte allerdings vermieden werden viele Elemente aus einer langen Liste herauszufiltern da dies viel Zeit in Anspruch nehmen kann. Stattdessen sollte versucht werden bereits innerhalb der Methode nur erlaubte Werte in die Collection einzutragen.

\subsubsection{Zugriffsbeschränkung auf Objektebene}

Man kann den Zugriff auf Objekte durch Überprüfen der jeweiligen Rolle oder auch über das Vorhandensein der notwendigen Berechtigungen (permissions) limitieren. Diese Permissions können pro Benutzer und Objekt vergeben werden und reichen von Standard \lstinline~BasePermission~s über selbsterstellte Permissions die von \lstinline~AbstractPermission~ abgeleitet sind \footnote{\url{http://static.springsource.org/spring-security/site/docs/3.0.x/reference/domain-acls.html}}.

Verwaltet werden solche Berechtigungen durch ACEs (AccessControlEntry) in ACLs (AccessControlList) die es pro Objekt nur einmal gibt. Implementiert wird dieses Konzept mittels vier Tabellen in der Datenbank. Dieses Schema muss vor Benutzung in der Datenbank angelegt werden damit es von Spring verwendet werden kann.

\begin{description}
	\item[ACL\_SID] SID steht für \emph{security identity}. Diese Tabelle enthält in einer Spalte die \lstinline~Principal~s (meist Benutzer) und \lstinline~GrantedAuthority~s und in einer zweiten Spalte ein Flag das kennzeichnet welche der beiden Arten die Zeile darstellt.
	\item[ACL\_CLASS] enthält alle Domänenobjekt-Klassennamen zusammen mit einer ID. Für jede Klasse für die ACL-Berechtigungen vergeben werden existiert eine Zeile.
	\item[ACL\_OBJECT\_IDENTITY] speichert Informationen über die eindeutigen Domänenobjekte. Die Tabelle enthält als Spalten eine ID, einen Fremdschlüssel auf die \lstinline~ACL\_CLASS~-Tabelle, einen eindeutigen Bezeichner welche das Objekt kennzeichnet, einen Fremdschlüssel auf \lstinline~ACL\_SID~ um den Besitzer der Objektinstanz zu speichern und ein Flag, ob ACL-Einträge von übergeordneten ACLs Berechtigungen erben können.
	\item[ACL\_ENTRY] speichert die individuellen Berechtigungen für jeden Rechte\emph{empfänger} (SID). Dazu gibt es als Spalten einen Fremdschlüssel auf \lstinline~ACL\_OBJECT\_IDENTITY~ und auf \lstinline~ACL\_SID~, ein Flag welches kennzeichnet ob ein Audit erstellt werden soll und eine Spalte mit einem 32 Bit Integer in dem die Berechtigungen als Bits kodiert sind.
\end{description}

Standardmäßig stehen die die ersten vier Bits für Lesen (Bit 0), Schreiben (Bit 1), Erstellen (Bit 2), Löschen (Bit 3) und Administrieren (Bit 4). Die restlichen Bits können über eine eigene \lstinline~Permission~-Instanz erweitert werden falls dies notwendig sein sollte.

Der folgende Beispielcode zeigt auf, wie ein Objekt, welchem wir die ID 42 (es kann auch der Hash oder irgendetwas eindeutiges verwendet werden) geben so gesichert wird, dass ein Principal mit dem Namen Samantha das Objekt administrieren darf.

\begin{lstlisting}
// Prepare the information we'd like in our access control entry (ACE)
ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(42));
Sid sid = new PrincipalSid("Samantha");
Permission p = BasePermission.ADMINISTRATION;

// Create or update the relevant ACL
MutableAcl acl = null;
try {
  acl = (MutableAcl) aclService.readAclById(oi);
} catch (NotFoundException nfe) {
  acl = aclService.createAcl(oi);
}

// Now grant some permissions via an access control entry (ACE)
acl.insertAce(acl.getEntries().length, p, sid, true);
aclService.updateAcl(acl);
\end{lstlisting}

\subsubsection{Beispielszenario}

Um SpringSecurity zum Absichern eines klinischen Studienverwaltungssystems zu verwenden, wird hier ein Beispielszenario entworfen und das Berechtigungsmodell mit SpringSecurity abgebildet.

Ein klinisches Studienverwaltungssystem soll mehrere Studien verwalten können. Diese Studien können jeweils auf mehrere Standorte (Sites) aufgeteilt sein. Das System verwaltet Patientendaten welche vor unerlaubtem Zugriff oder Veränderung geschützt werden müssen. Dazu werden dem Klinikpersonal Berechtigungen für die einzelnen Daten zugewiesen.

Es soll ein Berechtigungssystem mit Spring realisiert werden womit folgende Eigenschaften erfüllt werden:

\begin{description}
	\item[Patienten können nur vom Ersteller verändert werden] Damit nur der Ersteller schreibend auf seine Patienten zugreifen kann, werden ACLs genutzt und der jeweilige eintragende Benutzer mit Administratorrechten für diesen Patienten ausgestattet.
	\item[globale Rechte] Für das Personal das Zugriff auf alle Patientendaten benötigt soll es möglich sein, alle Daten einer Studie von allen Standorten auszulesen. Dazu kann die Vererbung von Rechten benutzt werden. Es werden ACEs für das jeweilige Studienobjekt eingetragen und dieses Studienobjekt als übergeordnetes Objekt (parent) der jeweiligen Standorte (studienspezifisch) genutzt. Die Patienten wiederrum können die ACLs von den Standort-ACLs vererbt bekommen
	\item[Standortbegrenzte Leserechte] Für Monitoringzwecke soll es möglich sein, dass Rollen existieren die lesend auf alle Patienten des jeweiligen Standortes zugreifen können. Um diese Rechte auf die Standorte einzuschränken, können dem Benutzer die Berechtigungen auf das jeweilige Standortobjekt (studienspezifisch) erteilt werden. Durch die Vererbung der ACLs können diese Rechte auch für die Patienten genutzt werden.
	\item[individuelle Rechte] Über ACEs die vom Objekteigentümer vergeben werden können ist es möglich anderen Benutzern Berechtigungen zu erteilen.
\end{description}
