Berechtigungen¶
Um Datensätze nur einer bestimmten Entity (Benutzer, Gruppen oder Rollen) zugänglich zu machen, kann man
Berechtigungen auf Record-Ebene vergeben. Dazu muss das zu speichernde Objekt
das \Alvine\Security\Authorization\AccessControlList
-Interface implementieren.
Mit dem \Alvine\Security\Authorization\AccessControlListImplementation
Trait
steht hierfür bereits eine fertige Implementierung zur Verfügung.
Klassenstruktur¶
Benutzer, Gruppen und Rollen¶
Alle Identitäten sind von dem zentralen Interface \Alvine\Security\Authentication\Entity
abgeleitet. Einer Entität
können über eine Zugriffsliste verschiedene Rechte zugeordnet werden.
Ist kein Benutzer bekannt oder ist der Benutzer noch nicht identifiziert, so kommt das \Alvine\Security\Authentication\Anonymous
Objekt zum Einsatz. Nach der Anmeldung wird der Benutzer zum authentifizierten Benutzer und wird über ein \Alvine\Security\Authentication\User
Objekt
abgebildet.
Zugriffsrechte¶
Rechte werden ebsonso wie Entitäten durch Klassen ausgedrückt. Im Bereich der Persitenz
sind die Rechte \Alvine\Persistence\Permission\Write
, \Alvine\Persistence\Permission\Read
und \Alvine\Persistence\Permission\Delete
definiert.
Jedes dieser Rechte steht für eine Operation. Benutzer die nur über das Recht Read verfügen, können das Objekt nicht ändern oder löschen.
AccessControlList¶
Zugriffsrechte und Entitäten werden in einer AccessControlList zusammengefasst. Das Interface \Alvine\Security\Authorization\AccessControlList
definiert die notwenidigen Funktionen und mit dem \Alvine\Security\Authorization\AccessControlListImplementation
Trait steht eine
fertige Implementierung zur Verfügung.
In dem folgenden Beispiel wird eine Zugriffsliste definiert. Hier sieht man, dass der der Benutzer $user
alle
drei Rechte hat. $object
ist in diesem Fall das zu speichernde Datenobjekt.
// Zugriffsrecte auf ein Objekt
$accessControl=new \Alvine\Security\Authorization\DefaultAccessControl();
// User darf lesen, schreiben und löschen
$accessControl->addEntity($user);
// Wenn diese Rechte eingeschränkt werden, wird weiter unten eine Exception geworfen.
$accessControl->addPermission(new Alvine\Persistence\Permission\Read());
$accessControl->addPermission(new Alvine\Persistence\Permission\Write());
$accessControl->addPermission(new Alvine\Persistence\Permission\Delete());
// Zugriffskontrolle in $object setzen
$object->addAccessControl($accessControl);
Implementierungsdetail
In der Standard-Implementierung der Zugriffsliste AccessControlListImplementation
wird die Berechtigung über eine
Assoziation in einem eigenen Objekt und nicht direkt im Datenobjekt gespeichert. Damit werden pro Speichervorgang zwei
Objekte geschrieben bzw. geladen. Je nach Konfiguration können die Objekte aus unterschiedlichen Storages kommen.
Beispiel¶
Das folgende Beispiel zeigt eine Implementierung der Zugriffsrechte.
/**
* Stringklasse mit Zugangsberechtigung
*/
class MyString extends Alvine\Types\StringType implements \Alvine\Security\Authorization\AccessControlList {
/**
* Standardimplementierung des \Alvine\Security\Authorization\AccessControlList
* Interfaces für die Zugangsberechtigung.
*/
use \Alvine\Security\Authorization\AccessControlListImplementation;
public function __construct($value=null) {
parent::__construct($value);
$this->initAccessControlList();
}
}
// Datenprovider & Storage-Objekt erstellen
// $mongoURL = 'mongodb://mongo.example.com/test/collection';
$provider=new Alvine\Persistence\Provider\MongoDB\DataObject(new Alvine\Net\Resource\URI($mongoURL));
$storage=new \Alvine\Persistence\ObjectStorage($provider);
// Handler mit SecurityContext ausstatten, da sonst der
// Manager davon ausgeht, dass der Handler keine Sicherheit
// unterstützt.
// Das kann mit einem Anonymen Benutzer erfolgen, da der
// Manager das später überschreibt.
$context=new Alvine\Persistence\SecurityContext(new \Alvine\Security\Authentication\Anonymous);
$storage->setSecurityContext($context);
// Der Manager sorgt für die Verwaltung der Objekte
// Der Manager kann auch über eine Eigenschaftsdatei initialisiert werden
// $manager->initPersitenceFromProperties()
$manager=\Alvine\Persistence\Manager::getInstance();
$manager->registerDefaultStorage($storage);
// Aktueller User
$user=new Alvine\Security\Authentication\User('me', '1425-0001');
// Der Manager muss über die entsprechende Identität verfügen.
// Damit kann er in den Storage-Objekten den SecurityIndex setzen.
$manager->setIdentity($user);
// Das eigentliche Datenobjekt
$string=new MyString();
// Zugriffsrecte auf dieses Objekt
$accessControl=new \Alvine\Security\Authorization\DefaultAccessControl();
// User darf lesen, schreiben und löschen
$accessControl->addEntity($user);
// Wenn diese Rechte eingeschränkt werden, wird weiter unten eine Exception geworfen.
$accessControl->addPermission(new Alvine\Persistence\Permission\Read());
$accessControl->addPermission(new Alvine\Persistence\Permission\Write());
$accessControl->addPermission(new Alvine\Persistence\Permission\Delete());
// Zugriffskontrolle setzen
$string->addAccessControl($accessControl);
$id=$string->getID();
// ID ausgeben
echo $id.Alvine\Types\Character::CRLF;
// Inhalt setzen
$string->string='Ich esse gerne Bananen!';
//
// Objekt in das Default-Objekt schreiben
try {
$result=$manager->writeObject($string);
} catch(Alvine\Persistence\Permission\ForbiddenException $ex) {
// Fallback, wird hier nicht aufgerufen.
echo "write not allowed".Alvine\Types\Character::CRLF;
exit(1);
}
// ... und im Anschluß Objekt im Speicher löschen
unset($string);
// Abfrage im Kontext eines Annoymen Benutzers.
$manager->setIdentity(new \Alvine\Security\Authentication\Anonymous());
// Objekt mit Anonymus versuchen zu laden
// sollte \Alvine\Persistence\Permission\ReadForbiddenException
// werfen.
try {
$obj=$manager->getObject(MyString::class, $id);
} catch(\Alvine\Persistence\ObjectNotFoundException $ex) {
echo "object not found".Alvine\Types\Character::CRLF;
exit(1);
} catch(\Alvine\Persistence\Permission\ReadForbiddenException $ex) {
echo "read not allowed".Alvine\Types\Character::CRLF;
// -> read not allowed
}
// Zweiter Versuch mit dem User der das Objekt geschrieben hat
$manager->setIdentity($user);
try {
$obj=$manager->getObject(MyString::class, $id);
} catch(\Alvine\Persistence\ObjectNotFoundException $ex) {
echo "object not found".Alvine\Types\Character::CRLF;
exit(1);
} catch(\Alvine\Persistence\Permission\ReadForbiddenException $ex) {
echo "read not allowed".Alvine\Types\Character::CRLF;
exit(1);
}
// ... und ausgeben der Zeichenkette
echo (string) $obj.Alvine\Types\Character::CRLF;
// -> Ich esse gerne Bananen!
// Objekt löschen
try {
$manager->deleteObject($obj);
} catch(\Alvine\Persistence\Permission\ForbiddenException $ex) {
}