Link

JCMS 5 : Personnalisation de la gestion des droits

In brief...
JCMS offre en standard une large palette de droits sur l'ensemble des fonctionnalités : droits de consultation, de contribution, de dépôt de fichier, d'administration, … Dans certains cas d'usage, il peut être nécessaire de spécialiser le contrôle de droit. Cet article décrit en détails les contrôles de droits fournis en standard par JCMS et explique comment les personnaliser avec la classe RightPolicy au travers de 3 exemples.
Subject Functional specification
Jalios API
Functional Administration
Products JCMS 5.5
JCMS 5.6
Published 8/24/06
Writer Olivier Dedieu
L'utilisation de RightPolicy a été mis à jour dans JCMS 5.7. Si vous utilisez cette version, reportez-vous à l'article JCMS 5.7 : Personnalisation de la gestion des droits.

1. Gestion des droits dans JCMS

JCMS offre en standard une large palette de droits sur l'ensemble des fonctionnalités : droits de consultation, de contribution, de dépôt de fichier, d'administration, … Néanmoins, pour certains besoins il peut être nécessaire de spécialiser la gestion de droit. La spécialisation peut se faire soit en complément soit en remplacement de l'implémentation standard.

Dans JCMS les droits sont affectés soit individuellement à des membres soit à des groupes. A partir de la version 5.6, JCMS permet de faire des groupes de groupes. Un membre qui appartient à un sous-groupe appartient automatiquement à tous les groupes parents de ce groupe (et aux parents des parents). Ainsi en affectant un droit à un groupe c'est non seulement les membres de ce groupe qui en bénéficient mais aussi tous les membres des sous groupes de ce groupe.

Cet article présente l'ensemble des droits de JCMS. Pour connaître les procédures de mise en œuvre de ces droits, il est conseiller de consulter le chapitre Droits du manuel utilisateur de JCMS.

2. Les grandes familles de droits

2.1 Droits sur les publications

2.1.1 Droits de consultation des publications

Ce droit contrôle qui peut consulter un contenu ou visualiser une portlet. Ce droit est défini contenu par contenu en indiquant les groupes et les membres autorisés. Si aucun droit n'est défini, la publication est visible de tous. Il est possible d'affecter des droits de consultation par défaut (par type de publication ou par espace de travail).

Le droit de consultation est conditionné :

  • à l'état du workflow dans lequel se trouve la publication : une publication hors de l'état publié n'est visible que dans le back-office de son espace de travail.
  • au rédacteur : quelques soient les droits de consultation, un membre a toujours accès aux contenus dont il est le rédacteur.

2.1.2 Droits de contribution

Ce droit contrôle qui peut créer, modifier ou supprimer des publications. Ce droit est défini par type de publication. Il est affecté pour un groupe ou pour membre.

Il est possible de définir un droit spécifique d'édition pour un contenu. Ceci permet à certains membres ou groupes n'ayant pas ce droit d'en bénéficier pour ces contenus.

Le droit de contribution est conditionné :

  1. Au droit de consultation : un utilisateur ne peut pas éditer ni supprimer une publication à laquelle il n'a pas accès ;
  2. A l'espace de travail : le contributeur ne bénéficie de son droit de contribution sur le type T dans un espace de travail que si cet espace utilise le type T ;
  3. Au workflow :
    1. Un membre ne peut créer une publication que si il est autorisé à travailler dans l'état initial du workflow de la publication.
    2. Un membre ne peut éditer ou supprimer une publication que si elle se situe dans un état de workflow où le membre peut agir ; c'est-à-dire un état pour lequel le membre occupe au moins un rôle de l'une des transitions sortantes de cet état.

2.1.3 Droits de dépôt des fichiers

Ce droit contrôle qui peut déposer des fichiers sur le site. Il s'agit en fait d'un droit dérivé du droit de contribution sur le type Document. Le membre doit avoir le droit de contribution sur le type Document

En standard, JCMS permet de contrôler le type et et la taille des fichiers déposés. Il est par exemple possible d'interdire le dépôt de fichiers vidéo ou de n'accepter que les fichiers PDF inférieurs à 10 Mo. Pour plus de détails, consulter la FAQ à ce sujet.

2.1.4 Droits d'accès aux fichiers

Le droit d'accès aux fichiers déposés est régi par les publications qui les pointent. Lorsqu'un utilisateur accède à l'un de ces fichiers, JCMS vérifie qu'il peut accéder à au moins une des publications qui référence ce fichier (soit un FileDocument, soit une publication avec un champ de type chemin de fichier).

2.1.5 Profils de consultation (audiencement)

A partir de la version 5.5, JCMS propose une autre approche pour la gestion des droits de consultation : les profils de consultation.

Le principe consiste à déterminer les droits de consultation en croisant les catégories d’un contenu et les catégories du membre qui accède au contenu. Pour cela, les membres doivent être catégorisés sur les mêmes branches que les contenus. Les rédacteurs n'ont plus à déclarer explicitement les droits de consultations mais simplement à quelles catégories sont rattachés les contenus.

Pour plus de détails, consulter l'article JCMS 5.5 : Profils de consultation (Audiencement).

2.2 Droits sur les catégories

2.2.1 Droits de consultation des catégories

Ce droit contrôle qui peut consulter une branche de catégories. Il est défini branche par branche pour un membre ou un groupe. Si un membre peut consulter la catégorie C, alors il peut aussi consulter toutes les sous-catégories de C.

Ce droit porte sur l'affichage des catégories (typiquement pour une Portlet Navigation). Il n'affecte pas les contenus situés sous ces catégories. En d'autres termes, un membre peut consulter les contenus référencés sous la catégorie C même si il n'a pas le droit de consulter C.

2.2.2 Droits d'usage des catégories

Ce droit contrôle qui peut référencer un contenu sous une branche de catégories. Il est défini branche par branche pour un membre ou un groupe. Si un membre peut référencer la catégorie C, alors il peut aussi référencer toutes les sous-catégories de C. Ce droit est conditionné au droit de contribution des publications.

2.2.3 Droits de gestion des catégories

Ce droit contrôle qui peut gérer une branche de catégories, c'est-à-dire créer, modifier, déplacer et supprimer des catégories. Il est défini branche par branche pour un membre ou un groupe. Si un membre peut gérer une catégorie C, alors il peut aussi gérer toutes les sous-catégories de C.

2.3 Droits d'administration

2.3.1 Droits d'administration d'un espace de travail

Ce droit contrôle qui peut administrer un espace de travail, c'est-à-dire :

  • Gérer les groupes de l'espace de travail;
  • Affecter les membres aux groupes ;
  • Gérer les affectations des rôles des workflows ;
  • Gérer les propriétés des types (workflows, droits par défaut, onglet affichés, …)
  • Consulter, éditer et supprimer toutes les publications et les catégories de l'espace de travail quelques soient leurs droits.

Ce droit est nominatif. Il est donné espace par espace par l'administrateur du site.

2.3.2 Droit d'administration centrale

Ce droit donne accès à toutes les fonctionnalités de JCMS. En plus des droits précédents, il permet de :

  • Gérer les comptes utilisateurs ;
  • Gérer les groupes ;
  • Gérer les espaces de travail ;
  • Gérer les modèles de workflow ;
  • Gérer les types de publications ;
  • Effectuer les tâches d'exploitation (configuration, indexation des publications, gestions des caches, …) ;
  • Effectuer les tâches de développement (définition des types de publication, gestion des changements, profiling, …)

2.4 Matrice d'affectation des droits

La matrice suivante indique qui peut affecter les droits.

  Contributeurs Gestionnaire
des catégories
Administrateur
d'espace de travail
Administrateur
central
Droits de consultation des publications (§2.1.1)

x

 

x

x

Droits de contribution (§2.1.2)

x

 

x

x

Droits de consultation des catégories (§2.2.1)  

x

x

x

Droits d'usage des catégories (§2.2.2)    

x

x

Droits de gestion des catégories (§2.2.3)    

x

x

Droits d'administration d'espace de travail (§2.3.1)      

x

Droits d'administration centrale (§2.3.2)      

x

 

3. Spécialisation des droits avec la classe RightPolicy

3.1 Principes

Il est possible d'adapter ou de modifier une partie du système de droits de JCMS en modifiant les méthodes de la classe RightPolicy. Le code de cette classe est ouvert et se situe dans le répertoire WEB-INF/classes/custom/RightPolicy.java. Chacune des méthodes statiques de cette classe permet de surcharger le comportement d'une famille de droit de JCMS.

La plupart des méthodes de la classe RightPolicy renvoient un booléen qui indique si le droit est validé ou non. Pour certaines méthodes de la classe RightPolicy, le premier argument de la méthode est un booléen (isAuthorized) qui indique si, selon les droits par défaut de JCMS, l'utilisateur peut accéder ou non à ce qu'il demande. Par défaut, ces méthodes renvoient ce booléen. Lorsqu'une de ces méthodes est modifiée, il est recommandé de rejeter l'accès si JCMS l'a lui aussi rejeté. C'est-à-dire renvoyer false si isAuthorized est false. Mais il est possible de passer outre le système de droit par défaut de JCMS en ignorant la position de JCMS.

Le contrôle de droit est très fréquemment invoqué par JCMS. Lors du rendu d'une page portail, certaines méthodes de la classe RightPolicy peuvent être appelées des centaines de milliers de fois. Il faut donc veiller à ce que l'implémentation de ces méthodes soit performante.

Une solution alternative à la spécialisation par la classe RightPolicy consiste à contrôler le système de droits programmatiquement via les APIs d'écriture. Ceci se fait typiquement en utilisant un DataController. Par exemple, pour affecter automatiquement un droit de consultation, il est possible à chaque enregistrement d'un contenu d'examiner les champs du contenu, d'en déduire le droit et d'affecter les membres ou groupes autorisés. Cette approche à l'avantage d'assurer de bonne performance lors du contrôle des droits mais ne permet pas de faire des droits contextuels (par exemple, basé sur l'adresse IP de provenance du membre.

Les méthodes de classe RightPolicy fournissent des informations qui permettent de déterminer le droit (p. ex. la publication concernée, le membre qu'il faut tester, …) Ces méthodes sont utilisés dans tous les cas de contrôle de droit et pas uniquement lorsque l'utilisateur accède depuis son navigateur à un page de JCMS. Par exemple, elles sont aussi appelées lorsque les mails de validation doivent être envoyés suite à un changement d'état programmé. Ces méthodes ne reçoivent donc pas d'information sur la requête HTTP. Cependant, si le droit doit être conditionné à des informations contextuelles à l'accès web (p. ex. l'adresse IP, le type de navigateur, …), ces informations sont accessibles via les méthodes channel.getCurrentServletRequest() et channel.getCurrentJcmsContext().

3.2 Droit de consultation des publications

Le droit de consultation des publications peut être modifié par les méthodes :

public static boolean canBeReadBy(boolean isAuthorized, Publication pub, Member mbr, boolean searchInGroups)

public static boolean canBeReadBy(boolean isAuthorized, Publication pub, Group grp)

La première méthode est invoquée lorsque le contrôle doit être fait sur un membre et la seconde sur un groupe. Pour la première méthode le booléen searchInGroups indique si le contrôle doit être fait uniquement avec les droits propres au membre ou en intégrant aussi les droits issus de ses groupes.

Les méthodes suivantes permettent de surcharger le comportement des profils de consultations (audiencement).

public static boolean isAudienced(Publication pub)

public static boolean checkAudienceRights(boolean isAuthorized, Publication pub, Member mbr, boolean searchInGroups)

Pour plus de détails sur ces méthodes, consulter l'article JCMS 5.5 : Profils de consultation (Audiencement).

3.3 Droit de consultation des catégories

Le droit de consultation des publications peut être modifié par les méthodes :

public static boolean canBeReadBy(boolean isAuthorized, Category cat, Member mbr, boolean searchInGroups, boolean checkAncestors)

public static boolean canBeReadBy(boolean isAuthorized, Category cat, Group grp, boolean checkAncestors)

La première méthode est invoquée lorsque le contrôle doit être fait sur un membre et la seconde sur un groupe. Pour la première méthode le booléen searchInGroups indique si le contrôle doit être fait uniquement avec les droits propres au membre ou en intégrant aussi les droits issus de ses groupes.

L'attribut checkAncestors indique si le contrôle porte sur la catégorie seule ou si il doit être étendu aux ancêtres de cette catégorie. Dans ce dernier cas, si le membre ou le groupe ne dispose pas du droit sur la catégorie, JCMS teste sur le parent, puis sur le parent du parent, et ainsi de suite jusqu'à ce qu'une catégorie accessible soit trouvée. Si la racine des catégories est atteinte sans avoir trouvé une catégorie autorisée alors l'utilisateur n'a pas accès à cette catégorie.

Il n'est pour l'instant pas possible de surcharger les droits d'usage et de gestion des catégories.

3.4 Droit de contribution

Le droit de contribution peut être modifié par la méthode :

public static boolean canWorkOn(boolean isAuthorized, Publication pub, Member mbr)

Cette méthode est invoquée à chaque fois que l'on doit déterminer si un membre peut éditer ou supprimer une publication.

Il n'est pour l'instant pas possible de modifier le contrôle de droit lors de la création d'une publication.

3.5 Droit de dépôt de fichier

Le droit de dépôt de fichier peut être modifié par la méthode :

public static boolean checkUpload(DocUploadInfo info, Member mbr, Workspace ws)

L'attribut info permet d'obtenir des informations sur le fichier (chemin, type, …).

L'attribut ws contient l'espace de travail dans lequel le fichier est déposé.

Cette méthode est invoquée à chaque fois une fois qu'un document est déposé. Si elle renvoie true, le fichier est déplacé de la zone temporaire de dépôt à son emplacement définitif. Sinon, le fichier est supprimé et l'utilisateur est prévenu du rejet.

3.6 Contrôle de contenu HTML

Lors de l'enregistrement d'une publication contenant des champs de type Texte Riche (avec un éditeur wysiwyg), le contenu de ces champs est vérifié. Ceci permet d'éviter qu'un contributeur mal intentioné introduise par exemple du code Javascript pour faire du Cross Site Scripting. Par défaut JCMS, passe une expression régulière définie par la propriété channel.forbidden-html qui est déclarée dans le fichier WEB-INF/data/webapp.prop.

Il est possible d'aller au-delà en modifiant la méthode :

public static ControllerStatus checkHtml(String str, String field)

L'attribut str contient le texte à vérifier

L'attribut field contient le nom du champ contenant ce texte.

La méthode retourne un ControllerStatus qui, en cas de rejet, permet de préciser un message d'explication.

4. Exemples de spécialisation

4.1 Filtrage selon la provenance de l'utilisateur

Dans cet exemple, on interdit l'accès aux publications de type SmallNews aux utilisateurs utilisant un navigateur embarqué sur un PDA ou un téléphone i-mode.

Pour cet exemple, la méthode canBeReadBy() est modifiée. Les contrôles par défaut (AudienceRight et isAuthorized) sont préservés. Ensuite, si il s'agit d'une SmallNews on contrôle le type de navigateur. La classe com.jalios.util.Browser fournit des informations sur le navigateur. Il est possible d'obtenir une instance correspondant à l'utilisateur qui fait la requête via la classe JcmsContext que l'on récupère via la méthode channel.getCurrentJcmsContext(). La méthode isSmallDevice() permet de tester si il s'agit d'un PDA ou d'un téléphone i-mode.

Pour tester cet exemple, si vous ne disposez pas d'un PDA ou d'un téléphone i-mode, vous pouvez utiliser un simulateur comme par exemple Phone Simulator d'OpenWave. Il suffit de consulter la page custom/jcms/indexPDA.jsp et de comparer le résultat lorsque l'on y accède avec un navigateur classique.

  public static boolean canBeReadBy(boolean isAuthorized, Publication pub, Member mbr, boolean searchInGroups) {

// Original code : Check right
if (AudienceRights.getInstance().isEnabled() && pub.isAudienced()) {
return checkAudienceRights(isAuthorized, pub, mbr, searchInGroups);
}

// Original code : Check JCMS status
if (!isAuthorized) {
return false;
}

// Only test SmallNews
if (!(pub instanceof generated.SmallNews)) {
return true;
}

// Check the Browser
Channel channel = Channel.getChannel();
JcmsContext ctxt = channel.getCurrentJcmsContext();
if (ctxt == null) {
return true;
}
Browser browser = ctxt.getBrowser();

return !browser.isSmallDevice();
}

4.2 Droit de validation conditionnel

Dans cet exemple, on met en place un système de distribution des contenus à valider selon une branche de catégories. Un validateur n'aura à valider que les contenus classés dans des catégories dont il a le droit de gestion.

Pour cet exemple, la méthode canWorkOn() est modifiée. Si la publication est dans l'état Soumis (-80) alors on vérifie que le membre a le droit de gérer au moins une des catégories de la publication.

  static int SUBMITTED_PSTATUS = -80;
public static boolean canWorkOn(boolean isAuthorized, Publication pub, Member member) {

// Reject if JCMS does not authorize
if (!isAuthorized) {
return false;
}

// Check only publication in "submitted" state
if (pub.getPstatus() != SUBMITTED_PSTATUS) {
return true;
}

// Get the categories of the publication
Set catSet = pub.getCategorySet();
if (Util.isEmpty(catSet)) {
return true;
}

// Get the categories the member can manage
Set rootSet = member.getCategoryRootSet();
if (Util.isEmpty(rootSet)) {
return false;
}

// Check if the publication is under a category the member can manage
for(Iterator it1 = catSet.iterator(); it1.hasNext();) {
Category cat = (Category)it1.next();
for(Iterator it2 = rootSet.iterator(); it2.hasNext();) {
Category root = (Category)it2.next();
if (cat == root || cat.hasAncestor(root)) {
return true;
}
}
}

return false;
}

4.3 Contrôle antivirus des fichiers déposés

Dans cet exemple, on souhaite déclencher un contrôle antivirus à chaque fois qu'un fichier est déposé dans JCMS. Si un virus est détecté, le fichier est supprimé et l'utilisateur est prévenu du rejet.

Pour analyser les fichiers, on utiliser l'antivirus AVG de Grisoft qui est disponible gratuitement pour Windows et Linux. Cette version est fonctionnelle mais limitée a un usage personnel ; ce qui convient pour illustrer cet exemple. Dans le cadre, d'un usage en entreprise il faudrait envisager l'achat d'une licence adaptée. Le code de l'exemple est conçu pour la version Windows.

Pour cet exemple, la méthode checkUpload() est modifiée. A chaque soumission, on lance l'exécutable avgscan.exe sur le fichier déposé avec le paramètre /REPORT afin qu'il génère un rapport d'analyse. Le rapport est ensuite lu ligne par ligne. Si le texte "No viruses found." est trouvé, le fichier est accepté ; sinon il est rejeté.

Pour tester cet exemple, il faut disposer d'un fichier infecté. Pour cela, il est conseillé d'utiliser un virus inoffensif et spécialement conçu pour les tests comme par exemple celui de EICAR. Attention ! Si AVG est actif, lors du dépôt du fichier eicar.com, il le neutralisera dès son enregistrement et JCMS acceptera un fichier vide. Il faut donc désactiver le contrôle automatique (au moins lors du test) pour laisser JCMS effectuer le contrôle et prévenir l'utilisateur.

  public static boolean checkUpload(DocUploadInfo info, Member mbr, Workspace ws) {

File file = info.getFile();
if (isInfected(file)) {
JcmsUtil.logSecurityIssue("Virus found in file " + file);
return false;
}

logger.info("No viruses found in " + file);
return true;
}

static String AVGSCAN = "\"C:\\Program Files\\Grisoft\\AVG Free\\avgscan.exe\"";

static boolean isInfected(File file) {
boolean isInfected = true;

File report = null;

// Run avgscan.exe
try {
report = File.createTempFile("avgreport", "txt");
report.deleteOnExit();

String cmdLine = AVGSCAN + " /REPORT " + report + " " + file;
Runtime.getRuntime().exec(cmdLine).waitFor();
}
catch (Throwable th){
logger.warn("Exception while running avgscan", th);
return true;
}

// Parse the report
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(report));
for(String line = br.readLine(); line != null; line = br.readLine()) {
if (line.equals("No viruses found.")) {
isInfected = false;
break;
}
logger.info(line);
}
br.close();
report.delete();
}
catch (IOException ex){
logger.warn("Exception while reading report " + file, ex);
IOUtil.closeQuietly(br);
}

return isInfected;
}


Member Discussions

    Title First post Last post Writer #Messages
1. Droits de consultation par défaut 12/11/07 11:52 AM 12/12/07 5:26 PM Nicolas Fouque 10

Login   Home   fr en
JALIOS SA - SIREN 440 126 035