Wikitty fournit un système de gestion des droits en lecture et en écriture pour les entitées. Vous pouvez aller jusqu'à limiter l'accès à certains objet d'un type à certains utilisateurs. Vous pouvez également accorder des droits différents à certains champs des objets.
Pour mettre en place la sécurité dans Wikitty, il suffit de rajouter org.nuiton.wikitty.services.WikittyServiceSecurity dans la liste des composants à utiliser de votre configuration:
wikitty.WikittyService.components=org.nuiton.wikitty.services.WikittyServiceStorage,org.nuiton.wikitty.services.WikittyServiceCached,org.nuiton.wikitty.services.WikittyServiceSecurity
Cela rajoute la couche de sécurité à Wikitty. Vous pouvez maintenant rajouter des droits à certaines entitées pour en limiter l'accès.
Si vous souhaitez utiliser le module de cache en même temps que le module de sécurité, cela implique une bonne utilisation et de faire attention à certaine chose. Il faut faire attention qu'un utilisateur qui a récupéré un objet ne le rende pas disponible à un autre utilisateur au travers du cache. Il faut donc que la couche de sécurité soit toujours au dessus de la couche de cache.
De la même façon, si l'on a mis du cache côté client dans certain cas, il faudra aussi remettre la couche de sécurité. Cela arrive si le côté client est multi-utilisateur. Si ce n'est pas le cas, il n'est pas nécessaire de le faire.
+--------------+ +--------------+ WClient ----->| sécurité |<----+ | sécurité |<------ WClient +--------------+ | +--------------+ | cache | | | cache | +--------------+ | +--------------+ | notification | | | notification | +--------------+ | +--------------+ | WS Impl | +----| WS Hessian | +--------------+ +--------------+ serveur client
Il est possible d'utiliser un moyen externe d'authentification, par exemple LDAP. Pour cela il faut implanter la classe WikittyServiceSecurityExternalAuthentication en implantant le mécanisme que l'on souhaite. Ensuite il faut l'ajouter a la configuration pour que le service de security l'utilise:
wikitty.WikittyService.components= org.nuiton.wikitty.WikittyServiceStorage, // ...autres.services..., org.nuiton.wikitty.services.WikittyServiceSecurity wikitty.WikittyServiceSecurity.components=packages.MyExternalAuthentication wikitty.security.externalAuthenticationOnly=true
Il faut bien vérifier que org.nuiton.wikitty.services.WikittyServiceSecurity est déclaré dans la configuration sinon l'option seule wikitty.WikittyServiceSecurity.components n'aura aucun effet.
La dernier option wikitty.security.externalAuthenticationOnly indique ici que si l'authentification sur MyExternalAuthentication échoue il ne faut pas essayer sur le local (par défaut on essaie en local)
Dans wikitty une implantation par défaut a été faite pour l'authentification LDAP Voici un exemple de configuration:
wikitty.WikittyService.components= org.nuiton.wikitty.WikittyServiceStorage, // ...autres.services..., org.nuiton.wikitty.services.WikittyServiceSecurity wikitty.WikittyServiceSecurity.components= org.nuiton.wikitty.services.WikittyServiceSecurityExternalAuthenticationLDAP wikitty.security.externalAuthentication.ldap.server=ldap://intranet.codelutin.home:389 wikitty.security.externalAuthentication.ldap.loginPattern=uid=%s,ou=People,dc=codelutin,dc=home
Les deux options obligatoires sont l'url du serveur et le format des logins (DN) le '%s' est remplacé par le login.
Il est possible d'ajouter toutes les options acceptées par JNDI en les préfixant par 'wikitty.security.externalAuthentication.ldap.jndi.' Par exemple on peut modifier la factory par défaut avec:
wikitty.security.externalAuthentication.ldap.jndi.java.naming.factory.initial
Voir la documentation JNDI pour toutes les options possibles
Dans Wikitty, deux notions sont utilisées pour gérer la sécurité : les utilisateurs (WikittyUser) et groupes (WikittyGroup).
Les utilisateurs ont un identifiant et un mot de passe, les groupes contiennent des utilisateurs et d'autres groupes.
Par défaut il existe un WikittyGroup portant le nom WikittyAppAdmin. Si ce groupe n'existe pas ou qu'il est vide, cela indique que tous les utilisateurs sont AppAdmin. Cela est nécessaire pour deux choses:
pour permettre d'avoir une authentification, mais que l'on ne souhaite pas de gestion d'autorisation.
pour servir de bootstrap au lancement de l'application seul les AppAdmin peuvent modifier le WikittyGroup portant le nom WikittyAppAdmin, or s'il est vide il faut pouvoir le remplir.
Il ne doit donc exister un seul WikittyGroup portant le nom WikittyAppAdmin
À chaque login, un token de sécurité est fourni à l'utilisateur. L'utilisateur doit fournir ce token à chaque opération pour montrer qu'il a les droits. Pour un token donné, on peut savoir à quel utilisateur il appartient. Pour le développeur, cela n'implique pas de changement car le token de sécurité est conservé par le WikittyClient. Il faut juste faire attention à bien avoir un WikittyClient par utilisateur. Dans le cas d'applications web, il est conseillé de conserver le client dans la session de l'utilisateur.
Les tokens sont stockés en base et supprimés au logout de l'utilisateur.
Les SecurityToken ne sont supprimés de la base de données qu'au moment du logout Si les utilisateurs/applications quittent sans faire le logout le nombre de SecurityToken ne fera qu'augmenter. Pour éviter cela, il faut prévoir un petit job qui de temps en temps fait le ménage dans les SecurityToken trop vieux.
La première chose à faire maintenant, est donc de créer l'utilisateur administrateur de l'application et l'ajouter au groupe WikittyAppAdmin:
WikittyUser admin = new WikittyUserImpl(); admin.setLogin("admin"); admin.setPassword("admin"); admin = client.store(admin); WikittyGroup adminGroup = WikittySecurityUtil.createAppAdminGroup(admin);
Note : il faut vérifier que le groupe existe avant de le créer).
A partir de maintenant, l'utilisateur administrateur (et tous les autres utilisateurs faisant partie du groupe WikittyAppAdmin) peut ajouter/retirer des droits à des entités.
Par exemple, pour rajouter les droits de lecture à un utilisateur (l'utilisateur admin est déjà identifié) sur un wikitty:
//On commence par charger les wikitties concernés WikittyAuthorisation skill = client.restore(WikittyAuthorisation.class, id); //On ajoute en reader notre utilisateur skill.addReader(user.getWikittyId()); //On enregistre client.store(skill);
On peut de la même manière ajouter un groupe en tant que reader/writer/owner/admin d'une entité.
Les droits sont les suivants :
Type |
Lecture |
Ecriture |
Suppression |
Changement de droits |
---|---|---|---|---|
Reader |
X |
|||
Writer |
X |
X |
||
Admin |
X |
X |
X |
X |
Owner |
X |
X |
X |
X |
AppAdmin |
X |
X |
X |
X |
Si on veut que tout le monde puisse lire un wikitty, il faut laisser vide la liste des readers (vide ou null).
Si l'on souhaite indiquer que personne ne peut lire l'objet il faut mettre le owner en tant que reader. Car de toute façon l'owner aura toujours le droit en lecture.
La granularité des droits se situe donc au niveau de chaque instance. On doit pouvoir définir le droit pour chaque extension, de chaque wikitty. Il n'y a pas de gestion des droits par champs. Avoir le droit reader sur une extension d'un wikitty donne le droit de lecture sur tous les champs de cette extension.
Un admin est administrateur d'une entité uniquement, alors qu'un AppAdmin est administrateur de toutes les entités de l'application.
Du point de vue structure de données, les droits sont stockés sur le wikitty lui-même, dans des champs spécifiques. Par exemple, si le wikitty porte l'extension Ext, il portera également l'extension « Ext:WikittySecurity » et il y aura, sur le Wikitty, un champ nommé « owner » (dont le FQN est « Ext:WikittySecurity.owner »).
Autre exemple, si un Wikitty porte 3 extensions, ayant chacune 10 champs. Le wikitty aura, au total, 42 champs : 3 × 10 champs + 3 extensions × 4 champs (les 4 champs de l'extension WikittySecurity).
Pour chaque extension, on a la même hiérachie de droit qui donnent des possibilités différentes :
Type |
Lecture- Création d'instances |
Ecriture |
Suppression |
Changement de droits |
---|---|---|---|---|
Reader |
X |
|||
Writer |
X |
X |
||
Admin |
X |
X |
X |
X |
Owner |
X |
X |
X |
X |
AppAdmin |
X |
X |
X |
X |
Si le reader est vide, tout le monde peut créer des instances de l'extension. Pour que seuls les AppAdmin et le owner puissent créer des instances, il faut mettre le owner en reader.
Si une extension ne dispose pas de ces informations, seuls les AppAdmin peuvent créer les instances et modifier l'extension.
Ces droits sont stockés sous le forme d'un Wikitty. Pour chaque extension connue, il y aura donc un Wikitty dont la seule extension sera WikittySecurity.
Chacun de ces wikitty aura pour identifiant « WikittySecurity:ExtensionName ». Cela permet de court-cuircuiter la recherche solR, et un passage par le réseau à chaque store/restore.