Formation continue Projet tuteuré CRÉATION DES COMPTES UTILISATEURS MOD24 UVSQ SUJET Le contexte du projet est celui du lycée Paul Lapie relatif à l épreuve E4 de l examen du BTS SIO. Il s agit de l application capable de créer des comptes utilisateurs dans la base de données relationnelle qui stocke le système d information du contexte. Le moteur de la base de données (SGBDR) est le produit Open Source Derby, propriété de la fondation APACHE. Les comptes utilisateurs à créer sont tout d abord saisis et/ou générés dans un fichier XML. Ce fichier est fourni avec le sujet. Puis l application qui est à développer exploite ce fichier afin de créer les comptes dans la base de données. XML (comptes utilisateurs à créer) Analyse (parsing) Représentation des comptes comme objets JPA Persistance Des comptes avec l'api JPA et JDBC SGBDR Derby L exploitation du fichier XML utilise la technologie appelée parsing (analyse). Il s agit ici d une analyse de type SAX (Simple API for XML). C est un processus événementiel. L interface de programmation SAX2 (API) est implémentée en standard dans le kit de développement JAVA (JDK1.7.0_xx). Chaque compte utilisateur est représenté par deux classes. La classe Compte et la classe Rôle. La relation entre les deux classes est mono-directionnelle dans le sens d'un compte vers ses rôles. Car un compte utilisateur peut avoir plusieurs rôles en fonction des applications utilisées. La correspondance objet-relationnel (mapping) est structurée pour que les deux classes mappent vers deux tables. Ainsi la classe Compte est reliée par une relation de 1 vers N à la classe Rôle, il en 1/5 JJLC FC-UVSQ
découle que la table ROLE possède une clé étrangère qui référence la clé primaire de la table COMPTE. Exemple d'extrait du fichier nouveaux_comptes.xml : <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE comptes SYSTEM "nouveaux_comptes.dtd" > <comptes> <compte date-creation="08/01/2014" nom-complet="dupont Pierre"> <login>dupont2014</login> <password>pierre2014</password> <role>user</role> <role>admin</role> <role>manager</role> </compte> <compte date-creation="08/01/2014" nom-complet=""> <login>martin2014</login> <password>isabelle2014</password> <role>user</role> </compte> </comptes> DTD qui structure le fichier nouveaux_comptes.xml : <?xml version="1.0" encoding="utf-8"?> <!ELEMENT comptes (compte+)> <!ELEMENT compte (login, password, role+)> <!ATTLIST compte nom-complet CDATA #IMPLIED <!ELEMENT login <!ELEMENT password (#PCDATA)> <!ELEMENT role (#PCDATA)> date-creation CDATA #REQUIRED> (#PCDATA)> attribut falcutatif attribut obligatoire Le processus d analyse et d extraction (parsing) des données pertinentes du fichier XML des comptes utilisateurs à créer repose sur deux classes techniques. La première classe implémente la partie logique événementielle du processus SAX. Il s agit de la classe ExtractionXML. Elle spécialise la classe org.xml.sax.helpers.defaulthandler. La seconde classe Parseur permet de piloter le parsing en utilisant le fichier XML et une instance de la classe ExtractionXML. La logique événementielle de l'analyse SAX repose sur la classe qui implémente les méthodes événementielles : startdocument(), enddocument(), startelement(), endelement() et characters(). startdocument() méthode appelée lorsque SAX rencontre le début du fichier XML qu'il analyse enddocument() startelement() endelement() characters() méthode appelée lorsque SAX rencontre la fin du fichier XML (EOF) méthode appelée lorsque SAX rencontre une balise ouvrante méthode appelée lorsque SAX rencontre une balise fermante méthode appelée lorsque SAX rencontre une valeur de type PCDATA Le parseur SAX n'appelle que les méthodes implémentées dans la classe de paramétrage, dans le cas présent la classe ExtractionXML. L'analyse du parseur SAX est séquentielle sans retour en arrière possible dans la hiérarchie des balises du fichier XML analysé. 2/5 JJLC FC-UVSQ
La classe ExtractionXML paramètre le comportement du parseur SAX. Elle ne peut pas également avoir la responsabilité de créer les objets persistants JPA. Elle doit donc être aidée par une autre classe technique qui elle a la responsabilité de créer les objets persistants. <<org.xml.sax>> + DefaultHandler + ExtractionXML + FabriqueDeCompte 1 +startdocument() +startelement() +characters() +endelement() +enddocument() -fabrique +demarrer() +enregistrer() +stoper() Méthode qui utilise l'api JPA grâce à un objet EntityManager La méthode characters() permet de récupérer les valeurs PCDATA, c'est à dire celles encapsulées entre une balise ouvrante et une balise fermante. Exemple d'implémentation de la méthode characters() : public void characters(char[] ch, int start, int length) throws SAXException { String valeurpcdata = new String(ch,start,length); System.out.println(valeurPCDATA); C'est dans la méthode startelement() qu'il est possible de paramétrer l'extraction des valeurs issues des attributs XML. Exemple d'implémentation de la méthode startelement() : public void startelement(string uri, String localname, String qname, Attributes attributes) throws SAXException { System.out.println(qName); // affiche le nom de la balise ouvrante for (int i = 0; i < attributes.getlength(); i++) { System.out.println(attributes.getLocalName(i)); // affiche le nom des // attributs d'une balise System.out.println(attributes.getValue(i)); // affiche la valeur des attributs // d'une balise 3/5 JJLC FC-UVSQ
La base de données qui est chargée de stocker les comptes utilisateurs et leurs rôles est structurée par une schéma relationnel composé de deux tables. La table qui mémorise les comptes et celle qui mémorise les rôles. Il faut que la persistance de ce modèle soit facilité pour l'application. C'est à dire que la classe technique FabriqueDeCompte ne soit pas obligée de rendre persistants les rôles d'un côté et les comptes de l'autre. Il faut que lorsqu'un objet compte est rendu persistant, son ou ses rôles le soient avec lui. Il s'agit d'une persistance transitive appelée «persistance par navigation» (persistence by reachability). Lorsque la racine du graphe d'objets persistants est passée en argument à la méthode persist(), alors tout le graphe est mappée vers les tables respectives et enregistré dans celles-ci. Ce comportement est possible grâce à l'annotation @OneToMany et à son attribut cascade. Extrait de la classe Compte : @Entity public class Compte { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int idcompte; @Column(nullable = true) private String nomcomplet; @Temporal(TemporalType.DATE) @Column(nullable = true) private Date datecreation; @Column(nullable = false) private String login; @Column(nullable = false) private String password; @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "COMPTE_FK") private List<Role> roles = new ArrayList<>(); public Compte() { super(); 4/5 JJLC FC-UVSQ
La base de données doit être protégée et donc sécurisée. Ainsi, seuls l'administrateur (DBA 1 ) et l'utilisateur associé à l'application (utilisateur application) qui crée les comptes utilisateurs ont accès à la base de données. Le processus de sécurisation repose sur le paramétrage du fichier derby.properties, à la variable d'environnement DERBY_OPTS et à la capacité du DBA de créer l'utilisateur application. 1. Création du fichier derby.properties 2. Modification du script de lancement du moteur relationnel Derby 3. Démarrage du moteur relationnel Derby en exécutant le script startderby.sh 4. Connexion à la base de données avec SQUIRREL avec les droits DBA (login : dba, mot de passe : dbapasswd) 5. Création de l'utilisateur application en SQL 6. Octroi des privilèges à l'utilisateur application en SQL 1 fichier derby.properties : derby.connection.requireauthentication=true derby.database.sqlauthorization=true derby.authentication.provider=builtin derby.user.dba=dbapasswd login mot de passe 2 script unix-linux de lancement de Derby : export JAVA_HOME=chemin jusqu'au répertoire jdk1.7.0_xx export JRE_HOME=$JAVA_HOME/jre export PATH=$JAVA_HOME/bin:$PATH export DERBY_HOME=$JAVA_HOME/db export DERBY_OPTS=-Dderby.system.home=chemin jusqu'au répertoire où est placé le fichier derby.properties $DERBY_HOME/bin/startNetworkServer& 5 commande SQL de création de l'utilisateur application : CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.user.application', 'appasswd') 6 login octroi des privilèges select et insert : revoke all privileges on COMPTE, ROLE from application grant select, insert on COMPTE, ROLE to application mot de passe extrait de la connexion JDBC dans le fichier persistence.xml : <property name="javax.persistence.jdbc.user" value="application"/> <property name="javax.persistence.jdbc.password" value="appasswd"/> 1 DBA : Data Base Administrator 5/5 JJLC FC-UVSQ