Authentification de portlets
Pour les ressources protégées par le portail, HCL Digital Experience utilise les accréditations CORBA et un cookie LTPA chiffré afin d'authentifier les utilisateurs. Cependant, pour les systèmes dorsaux qui imposent d'utiliser leur propre identification, les portlets doivent assurer une certaine forme d'authentification afin d'accéder à ces applications distantes. Afin de proposer le système de connexion unique, les portlets doivent pouvoir enregistrer et retrouver les accréditations pour l'application qui leur est associée. Ils les utilisent ensuite pour se connecter pour le compte de l'utilisateur. HCL DX propose un coffre des données d'identification, où les utilisateurs et les administrateurs peuvent enregistrer en toute sécurité les données d'identification, à fins d'authentification. S'ils sont écrits pour, les portlets peuvent extraire les données d'identification de ce coffre, et se charger de la phase de connexion à la place de l'utilisateur.
Organisation du coffre des données d'identification
- L'administrateur de portail peut partitionner le coffre en plusieurs segments de coffre. Les segments de coffre ne peuvent être créés et configurés que par les administrateurs.
- Un segment de coffre contient un ou plusieurs emplacements de coffre. On peut les comparer à des "tiroirs", dans lesquels les portlets viennent enregistrer et récupérer les données d'identification d'un utilisateur. Chaque emplacement contient une accréditation.
- Un emplacement de coffre est associé à une ressource dans l'implémentation du coffre.
- Une implémentation de coffre est un espace dans lequel les données d'identification des utilisateurs sont enregistrées. Parmi les implémentations de coffres, on peut citer le coffre de base de données par défaut ou le boîtier de sécurité de Security Access Management Family.
- La ressource figurant dans l'implémentation du coffre correspond à une application ou à un système dorsal qui exige sa propre authentification. Parmi les exemples de ressources figurent Lotus Notes, des enregistrements personnels ou un compte bancaire.
Segments de coffre
Un segment de coffre est marqué comme étant géré par l'administrateur ou par l'utilisateur. Bien que les portlets puissent, pour le compte d'un utilisateur du portail, définir et récupérer des données d'identification dans ces deux types de segments, ils ne peuvent créer d'emplacements de données d'identification que dans les segments de coffre gérés par l'utilisateur. La figure ci-dessous montre de quelle façon les segments de coffre gérés par l'administrateur peuvent être répartis entre plusieurs implémentations du coffre. Il n'existe qu'un seul segment de coffre géré par l'utilisateur et il se trouve dans le coffre de personnalisation par défaut fourni par HCL DX.

Emplacements de coffre
- Emplacements de coffres dans les segments de coffre gérés par l'administrateur :
- Un emplacement système stocke toutes les données d'identification système dont le secret est partagé entre les utilisateurs et les portlets. Il s'agit d'un emplacement partagé qui appartient à un segment administratif. Ce type d'emplacement peut être créé via le portlet d'administration Coffre des données d'identification, en ajoutant un emplacement dans un segment de coffre géré par un administrateur et en le marquant partagé.
- Un emplacement administratif permet à chaque utilisateur d'enregistrer un code secret associé à une ressource définie par l'administrateur (par exemple, Lotus Notes). Il s'agit d'un emplacement non partagé qui appartient à un segment administratif. Ce type d'emplacement peut être créé via le portlet d'administration Coffre des données d'identification, en ajoutant un emplacement dans un segment de coffre géré par un administrateur et en ne le marquant pas comme partagé.
- Emplacements de coffres dans les segments de coffre gérés par l'utilisateur :
- Un emplacement utilisateur partagé enregistre les données d'identification utilisateur qui sont partagées entre les portlets de l'utilisateur. Il s'agit d'un emplacement partagé qui appartient à un segment utilisateur. Utilisez le portlet Coffre d'accréditation pour créer l'emplacement partagé. Définissez shared slot sur true.
- Un emplacement privé de portlet enregistre les données d'identification utilisateur qui ne sont pas partagées entre les portlets. Il s'agit d'un emplacement non partagé qui appartient à un segment utilisateur. Utilisez le portlet Coffre d'accréditation pour créer l'emplacement partagé. Définissez shared slot sur false.
| Type d'emplacement de coffre | Type de segment | Partagés | Création via | Partage du code secret |
|---|---|---|---|---|
| Emplacement système | géré par l'administrateur | conforme | Portlet d'administration Coffre des données d'identification | un code secret par système, partagé entre tous les utilisateurs et les portlets |
| Emplacement administratif | géré par l'administrateur | false | Portlet d'administration Coffre des données d'identification | un code secret par utilisateur, partagé entre tous les portlets des utilisateurs |
| Emplacement utilisateur partagé | géré par l'utilisateur | conforme | Service du portlet Coffre des données d'identification | un code secret par utilisateur, partagé entre tous les portlets des utilisateurs |
| Emplacement privé de portlet | géré par l'utilisateur | false | Service du portlet Coffre des données d'identification | un code secret par utilisateur et par entité de portlet, non partagé entre les portlets |
Objets d'accréditation
- API de portlet standard
com.ibm.portal.portlet.service.credentialvault.credentials.Credential
Object userSecret = credential.getUserSecret();
< portlet connects to backend system authenticates using the user's secret >
< portlet can use the connection to communicate with the backend application >
< portlet takes care of logging at the backend >
Tous les types de données d'identification disponibles dans le portail sont enregistrés dans une base de registres. HCL DX dispose d'un nombre réduit de types de données d'identification, mais d'autres objets de ce type peuvent être enregistrés dans cette base de registres.
L'interface PassiveCredential hérite de l'interface de base de données d'identification. Les rubriques suivantes décrivent les différents types d'objets de données d'identification passifs fournis par HCL DX :
- Objets d'accréditation passifs:
- SimplePassive
- Cet objet de données d'identification enregistre les codes secrets sous forme d'objets Java sérialisables. Comme le service de coffre ne supporte pas encore les codes secrets de type BLOB (binary large object), cet objet est réservé à une utilisation future.
- UserPasswordPassive
- Cet objet de données d'identification enregistre les codes secrets sous forme de paires ID utilisateur/mot de passe.
- JaasSubjectPassive
- Cet objet d'accréditation enregistre les codes secrets sous forme d'objets javax.security.auth.Subject. Là aussi, ce type de secret ne peut pas encore être enregistré par le service de coffre. Il est utilisé comme donnée d'identification transitoire non persistante, prise dans la session utilisateur.
- BinaryPassiveCredential
- Cet objet d'accréditation enregistre les codes secrets sous forme de tableau d'octets.
- Enregistrement des objets d'accréditation dans PortletSession
Les objets de données d'identification n'implémentent pas la méthode
java.io.Serializable, ils ne peuvent donc pas être enregistrés dansPortletSessionpour des raisons de sécurité. Les classes de données d'identification enregistrent le secret lui-même, sous forme d'un attribut privé. Ce code pourrait donc être découvert par quiconque a accès à la base de données de session du serveur d'application.Vous pouvez cependant enregistrer un objet de données d'identification dans
PortletSession, s'il n'est pas sérialisé dans un environnement en cluster. Une façon consiste à définir une classe de conteneur de données d'identification, qui enregistre l'objet de données d'identification lui-même, sous forme d'un membre transitoire. Un tel conteneur peut alors être enregistré sans problème dansPortletSession. Vous devez vérifier si l'objet de données d'identification a été perdu par une sérialisation, et dans ce cas, de le récupérer de nouveau depuis le coffre.Figure 1. Exemple : Conteneur de session d'objet de données d'identification. import com.ibm.portal.portlet.service.credentialvault.credentials.Credential; public class CredentialSessionContainer implements java.io.Serializable { private transient Credential credential = null; public void setCredential(Credential cred) {this.credential = cred;} public Credential getCredential() {return credential;} public boolean hasCredential() {return credential != null;} }
Scénarios d'utilisation du coffre des données d'identification
- Utiliser un emplacement existant, défini par l'administrateur de portail, dans un segment de coffre géré par l'administrateur.
- Créer un emplacement dans un segment de coffre géré par l'utilisateur.
Votre choix dépend de la façon dont le portlet est utilisé. En règle générale, la meilleure solution masque les détails techniques du coffre de données d'identification aux yeux des utilisateurs. Voici quelques exemples d'utilisation d'emplacements de données d'identification
- Portlet de courrier intranet Lotus Notes
- Une société possède un portail intranet pour ses employés. Chaque utilisateur du portail possède un compte de courrier Lotus Notes, et un portlet de courrier Lotus Notes est déployé et pré-configuré sur l'une des pages par défaut de l'employé, sur le portail.
- Solution conceptuelle.
- Le portlet de courrier Lotus Notes nécessite d'enregistrer le mot de passe Notes de l'utilisateur. Mais comme un grand nombre d'utilisateurs se servent de ce portlet, l'administrateur doit créer pour ce portlet un emplacement des données d'identification Lotus Notes à l'aide du portlet d'administration Coffre des données d'identification. A l'aide du mode de configuration du portlet, l'administrateur définit l'ID de l'emplacement de coffre de toutes les entrées de portlet. Le portlet permet aux utilisateurs de définir leur mot de passe Notes personnel dans le mode édition. Le portlet peut enregistrer le mot de passe de chaque utilisateur dans le coffre de données d'identification.
- Si l'entreprise utilise un serveur Domino® dans le même domaine de connexion unique que le portail, il est possible d'utiliser des données d'identification LTPAToken fondées sur le sujet JAAS de l'utilisateur. Ces données d'identification permettent d'accéder au serveur Domino via une connexion authentifiée qui réutilise le jeton LTPA de l'utilisateur.
- Portlet d'inventaire
Le service achats d'une entreprise utilise un portail qui intègre plusieurs applications anciennes. L'une d'elles, une application de commande qui tourne sur un ancien système, se connecte directement aux systèmes des fournisseurs. Plusieurs employés utilisent ce portlet. Toutefois, l'application mainframe est sécurisée par un seul ID système : elle ne prend pas en charge plusieurs comptes utilisateur.
Solution conceptuelle : Le portlet de commande doit accéder à l'application de commande sous l'ID système. L'administrateur configure l'ID d'emplacement du coffre pendant le déploiement du portlet. L'administrateur du portail crée donc un emplacement de coffre dans un segment de coffre géré par l'administrateur et le marque en tant que données d'identification système. L'administrateur utilise le portlet de coffre d'accréditation pour enregistrer dans cet emplacement l'ID du système de commande et le mot de passe correspondant. Les employés du service achats n'ont plus besoin de se soucier des données d'identification.
- Portlet POP3 de fédération de mail Internet
Un portail de communauté Internet propose entre autres un portlet fédérateur de mail, capable de relever le courrier de plusieurs comptes POP3.
Solution conceptuelle : Ce portlet n'est qu'une fonction parmi d'autres, il est donc probable qu'il ne sera pas utilisé par tous. De plus, il est difficile de savoir le nombre de comptes qu'un utilisateur veut fédérer. Par conséquent, cela ne vaut pas la peine que l'administrateur du portail crée un emplacement de coffre pour ce portlet. A la place, le portlet fournit aux utilisateurs une configuration conviviale, dans son mode édition. Ils peuvent ajouter le nombre de boîtes aux lettres POP3 dont ils ont besoin. Le portlet crée un emplacement de coffre pour chacune des boîtes de l'utilisateur dans le segment de coffre géré par l'utilisateur.
En théorie, un utilisateur peut configurer deux instances du portlet sur une page, par exemple une pour ses comptes professionnels, et une autre pour ses comptes personnels. Ainsi, comme il n'y a probablement aucune raison de partager les données d'identification courrier de cet utilisateur avec d'autres portlets, les emplacements de données d'identification créés sont marqués comme étant privés par le portlet.
Echantillons de coffre des données d'identification
Cette section contient un exemple de code pour l'utilisation du service de coffre des données d'identification. Pour plus d'informations sur les méthodes CredentialVaultService, voir la documentation Portlet API Javadoc.
- Exemple de portlet standard dans Rational Application Developer
Lorsque vous utilisez l'assistant de portlet dans Rational Application Developer pour créer des portlets qui utilisent le service du portlet du coffre des données d'identification, l'assistant génère une classe SecretManager qui gère les tâches communes. Le bean de session généré par l'assistant inclut des méthodes getter (accesseur) et des méthodes SET pour le type de code secret et le nom d'emplacement de coffre. Les exemples suivants indiquent du code qui peut être généré pour vous, selon vos sélections, lorsque vous créez un projet de portlet JSR 168.
Remarque : Ce code est uniquement une démonstration de l'utilisation du coffre des données d'identification. Tout code généré doit subir une personnalisation supplémentaire pour répondre à vos besoins spécifiques en matière d'application.- Extraire le service du portlet du coffre des données d'identification. Ce code est placé dans la méthode init() de SecretManager et est appelé à partir de la méthode init() de la classe de portlet principale. Voir Accès aux services de portlet pour plus d'informations sur l'extraction des services de portlet à l'aide de JNDI.
Figure 2. Extraction du service de coffre d'accréditation public static void init(PortletConfig config) throws PortletException { try { if( vaultService == null ) { Context ctx = new InitialContext(); PortletServiceHome cvsHome = (PortletServiceHome)ctx.lookup("portletservice/com.ibm.portal.portlet. service.credentialvault.CredentialVaultService"); if (cvsHome != null) { vaultService = (CredentialVaultService)cvsHome.getPortletService (CredentialVaultService.class); } } } catch (Exception e) { throw(new PortletException("Error on init()", e)); } } - Définir les données d'identification. La méthode processAction() du portlet extrait les paramètres USERID et PASSWORD du JSP d'édition lors de la demande d'action. Si les deux paramètres n'ont pas la valeur NULL ils sont utilisés pour définir les données d'identification.
Figure 3. Obtention des données d'identification lors de la demande d'action if( request.getParameter(USER_SUBMIT) != null ) { // Set userId/password text in the credential vault PortletSessionBean sessionBean = getSessionBean(request); if( sessionBean!=null ) { String userID = request.getParameter(USERID); String password = request.getParameter(PASSWORD); // save only if both parameters are set if(userID!=null && password!=null && !userID.trim().equals("") && !password.trim().equals("")) { try { SecretManager.setCredential(request,sessionBean,userID,password); } catch (Exception e) { //Exception Handling } } } }La méthode setCredential() de la classe SecretManager détermine si le portlet peut écrire dans l'emplacement et si l'ID d'emplacement possède du contenu. Si c'est le cas, il utilise la méthode setCredentialSecretUserPassword() du service de coffre des données d'identification pour définir les données d'identification sur l'emplacement.
Figure 4. Définition des données d'identification public static boolean setCredential(PortletRequest portletRequest, PortletSessionBean sessionBean, String userID, String password) throws PortletException { try { if( isWritable(sessionBean) ) { String slotId = getSlotId(portletRequest,sessionBean,true); // create slot if necessary if( slotId != null ) { vaultService.setCredentialSecretUserPassword(slotId,userID,password. toCharArray(),portletRequest); return true; } } } catch( CredentialVaultException e) { //Exception Handling } return false; } - Obtenir un emplacement pour stocker les données d'identification de l'utilisateur. La méthode setCredential() appelle cette méthode pour créer un emplacement ou pour utiliser un emplacement existant accessible.
- Le nom de l'emplacement est défini comme préférence de portlet pour que l'administrateur puisse le remplacer par tout emplacement créé à l'aide de l'interface d'administration du portail.
- Pour un emplacement privé de portlet, cette méthode crée un nouvel emplacement si le nom de l'emplacement dans les préférences de portlet est null. La méthode createNewSlot() est une autre méthode personnalisée de SecretManager qui utilise la méthode createCredentialSlot() du service du coffre des données d'identification. Cette méthode peut créer des emplacements en dehors du système et renvoie un objet CredentialSlotConfig. Le slotID de ce nouvel emplacement est stocké dans les préférences du portlet et est utilisé pour mettre à jour et extraire les données d'identification privées du portlet.
- Pour un emplacement partagé, cette méthode recherche un nom de ressource partagée dans des emplacements accessibles. Si aucun emplacement partagé n'est disponible, elle crée un emplacement.
Figure 5. Création d'un emplacement ou utilisation d'un emplacement existant private static String getSlotId(PortletRequest portletRequest, PortletSessionBean sessionBean, boolean bCreate) throws PortletException { String slotId = null; String slotName = sessionBean.getVaultSlotName(); switch( sessionBean.getSecretType() ) { case SECRET_PORTLET_PRIVATE_SLOT: PortletPreferences prefs = portletRequest.getPreferences(); String prefsKey = ".slot."+portletRequest.getRemoteUser()+". "+slotName; slotId = prefs.getValue(prefsKey,null); if( slotId==null && bCreate ) { slotId = createNewSlot(portletRequest,slotName, true); // create private slot if( slotId != null ) { try { prefs.setValue(prefsKey,slotId); prefs.store(); } catch( Exception e ) { throw(new PortletException("Error on PortletPreferences. store()", e)); } } } break; case SECRET_SHARED_SLOT: try { Iterator it = vaultService.getAccessibleSlots(portletRequest); while( it.hasNext() ) { CredentialSlotConfig config = (CredentialSlotConfig)it.next() ; //searches for shared resource name if( config.getResourceName().startsWith(slotName ) ) { slotId = config.getSlotId(); break; } } if( slotId==null && bCreate ) slotId = createNewSlot(portletRequest,slotName,false); // create shared slot } catch( CredentialVaultException e) { // exception handling goes here } break; default: slotId = slotName; break; } return slotId; } - Extraction des données d'identification Les méthodes doView() et doEdit appellent getCredential() à partir de SecretManager. Dans le cas de données d'identification passives, ce portlet définit les paramètres USERID et PASSWORD renvoyés à partir de cette méthode en tant qu'attribut dans la demande.
Figure 6. Définition de données d'identification passives StringBuffer userId = new StringBuffer(""); StringBuffer password = new StringBuffer(""); try { SecretManager.getCredential(request,sessionBean,userId, password); } catch( Exception e ) { getPortletContext().log("Exception on SecretManager.getCredential(): "+e.getMessage()); } request.setAttribute(USERID,userId.toString()); request.setAttribute(PASSWORD,password.toString());La méthode getCredential() de SecretManager gère les types UserPasswordPassiveCredential. Le type d'accréditation est défini comme un entier dans les préférences du portlet. La méthode getCredential() du service du coffre des données d'identification permet d'obtenir les données d'identification stockées dans l'emplacement.Figure 7. Méthode getCredential() public static void getCredential(PortletRequest portletRequest, PortletSessionBean sessionBean, StringBuffer userid, StringBuffer password) throws PortletException { try { String slotId = getSlotId(portletRequest,sessionBean,false); if( slotId != null ) { UserPasswordPassiveCredential credential = (UserPasswordPassiveCredential)vaultService.getCredential (slotId,CredentialTypes.USER_PASSWORD_PASSIVE,new HashMap(),portletRequest); if( credential != null) { userid.append(credential.getUserId()); password.append(String.valueOf(credential.getPassword())); } } } catch( CredentialVaultException e) { // exception handling goes here } }
- Extraire le service du portlet du coffre des données d'identification.
Modification du chiffrement du coffre des données d'identification
HCL DX prend en charge l'ajout de différents adaptateurs de coffre pour le stockage et l'extraction des données d'identification. L'adaptateur de coffre par défaut fourni avec HCL DX stocke des données d'identification dans la base de données de configuration du portail. Par défaut, les mots de passe sont masqués, mais ne sont pas chiffrés. Il existe un point de branchement de chiffrement permettant de chiffrer les mots de passe à l'aide d'un chiffrement personnalisé. Les sections ci-après décrivent une logique de chiffrement personnalisée qui peut être branchée à l'infrastructure de coffre des données d'identification existante.
Personnalisation du chiffrement
Pour écrire un exit de chiffrement personnalisé pour l'adaptateur de coffre par défaut, vous devez implémenter l'interface EncryptionExit qui est fournie par HCL DX, puis la déployer.
- Ecrivez une classe qui implémente l'interface SPI publique suivante : com.ibm.portal.portlet.service.credentialvault.spi.EncryptionExit.
Figure 8. Package d'interface d'exit de chiffrement com.ibm.portal.portlet.service.credentialvault.spi ; exit de chiffrement d'interface publique { /**This method is called during portal start up*/ public void init() throws CredentialVaultException; /**This method is called during portal shut down*/ public void destroy(); /**Encrypts the password. The password is only stored encrypted. After *getting it from the store it needs to be decrypted.*/ public char[] encryptPassword(char[] password) throws CredentialVaultException; /**Decrypts the password as a char[]*/ public char[] decryptPassword(char[] password)throws CredentialVaultException; } - Pour déployer une nouvelle classe dans HCL DX, créez un fichier JAR avec la nouvelle classe d'exit de chiffrement.
- Définissez le nom des propriétés de votre fichier d'adaptateur dans le fichier : <wp_root>/shared/app/config/services/VaultService.properties à default.config=defaultvault.properties.
- Créez un fichier defaultvault.properties avec le contenu suivant : encryptionExit=com.yourcompany.YourEncryptionExit
- Déployez le code sur HCL DX. Pour plus d'informations sur la procédure de déploiement du code sur HCL DX, voir Extension du chemin d'accès aux classes d'HCL DX.
- Redémarrez HCL DX.Après le redémarrage du serveur de portail, l'adaptateur de coffre par défaut lit la configuration modifiée et instancie la nouvelle classe d'exit de chiffrement à l'aide de sa méthode init(). Tous les droits d'accès en écriture et en lecture au coffre des données d'identification qui sont gérés par l'adaptateur de coffre par défaut utilisent à présent l'exit de chiffrement personnalisé pour les mots de passe provenant des données d'identification d'ID/de mot de passe utilisateur. Les données d'identification binaires ne sont pas chiffrées.Important : Si vous modifiez la logique de chiffrement de votre portail, les mots de passe existants déjà stockés dans le coffre des données d'identification deviennent inutilisables car ils sont encore codés avec la logique par défaut. Par conséquent, il est préférable de brancher votre logique de chiffrement personnalisé avant d'utiliser le système dans un environnement de production. Les mots de passe existants doivent être retapés manuellement par les utilisateurs du portail afin d'adopter la nouvelle logique de chiffrement. Une fois le mot de passe retapé, il utilise l'exit de chiffrement personnalisé et il peut être à nouveau correctement extrait.