Cours SpringBoot [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

1

Programmation Web avancée niveau 2 (Partie1): Spring

2

Présentation du cours • Objectif : savoir réaliser une application Spring de bout en bout ▫ En comprenant correctement le fonctionnement du framework ▫ En comprenant rapidement les parties de Spring

• Se familiariser avec des outils utilisés dans l’industrie • Ce cours est basé sur les versions suivantes ▫ Spring Framework 4.3 ▫ JPA 2.1

3

Bibliographie • Spring par la pratique par Julien Dubois, JeanPhilippe Retaillé, Thierry Templier, Eyrolles, 2006, 517 p., (ISBN 2212117108) • Spring par l'exemple par Gary Mak, PEARSSON, 2008, 492 p., (ISBN 2744023396) • Cours Spring, Mohamed Youssefi. • Le framework Spring, Claude Duvallet.

4

•Introduction à Spring •Architecture de Spring •Les bonnes pratiques dans Spring

5

Introduction à Spring (1/4) Problématiques • Les développements Java/JEE, notamment ceux qui utilisent les EJB, sont réputés complexes, tant en terme de développement que de tests et de maintenance. ▫ JEE impose une plateforme d’exécution lourde, qui pose des problèmes d’interopérabilité entre les différentes implémentations. ▫ Les développements JEE se caractérisent par leur forte dépendance et s’avèrent souvent difficiles à tester

6

Introduction à Spring (2/4) Motivation • Simplifier et structurer les développements JEE de manière à respecter les meilleures pratiques d’architectures logicielles. Utiliser le framework Spring pour concevoir des applications performantes, faiblement couplées, facilement testables et dont le code est réutilisable

7

Introduction à Spring (3/4) Qu’est-ce que Spring ? • Framework offrant un cadre de développement en se basant sur des «bonnes pratiques» • A l’origine orienté Java et Java EE ▫ Aujourd’hui d’autres implémentations existent : .NET et Python

• Un conteneur « léger» ▫ Facilite le développement avec des POJO (Plain Old Java Object) qui n’ont pas besoin d’être exécutés dans un conteneur/serveur d’application spécifique ▫ Permet d’avoir des composants «faiblement couplés» ▫ Améliore la qualité du code et facilite les tests

8

Introduction à Spring (4/4) Evolution et historique

9

Architecture Spring (1/5) • Spring se compose d’un noyau (Core Container) et de plusieurs modules

10

Architecture Spring (2/5) • Spring Core Container : regroupe les modules de base pour mettre en œuvre le conteneur ▫ Spring Core et Spring Beans : contiennent les fonctionnalités de base notamment le conteneur et des utilitaires ▫ Spring Context : propose un support de la définition du context Spring (sa configuration) mais aussi des fonctionnalités de base comme le mail, l'internationalisation, JNDI, ... ▫ Spring Expression Langage (SpEL) : propose un langage d'expressions pour interroger et manipuler les objets gérés par le conteneur

11

Architecture Spring (3/5) • AOP and Instrumentation : permet de mettre en œuvre la programmation orientée aspect en interne par Spring ou bien par les utilisateurs de Spring • Data Acces/Integration : regroupe les modules d'accès aux données ▫ Spring JDBC : propose une abstraction de l'utilisation de JDBC avec notamment une hiérarchie d'exceptions dédiées ▫ Spring ORM : propose un support pour des outils de type ORM (JPA, JDO, Hibernate, iBatis) ▫ Spring Transaction : propose un support déclaratif et par programmation de la gestion des transactions ▫ Spring OXM : propose une abstraction pour le mapping objet/XML ▫ Spring JMS : propose des fonctionnalités pour faciliter la mise en œuvre de JMS avec Spring

12

Architecture Spring (4/5) • Web : regroupe les modules pour le développement d'applications web ▫ Il contient notamment Spring Web MVC, la solution de Spring pour les applications Web, et propose une intégration avec de nombreux frameworks Web et des technologies de vue.

• Test : propose des fonctionnalités pour les tests automatisés avec Spring avec un support de JUnit et TestNG

13

Architecture Spring (5/5) • Autres extensions Spring: ▫ ▫ ▫ ▫

Spring Security Spring Android Spring .Net Etc.

14

Utilisation du Framework Spring

15

Les bonnes pratiques dans Spring

Décomposition en couches

Programmation par contrat

Singleton

Inversion de contrôle

Programmation par Aspect

16

Les bonnes pratiques dans Spring: Décomposition en couches (1/2) • Principe: la division en couches est une technique répandue pour décomposer logiquement un système complexe • Décomposer un système en couches présente de nombreux avantages, notamment les suivants : ▫ possibilité d’isoler une couche, afin de faciliter sa compréhension et son développement ; ▫ très bonne gestion des dépendances ; ▫ possibilité de substituer les implémentations de couches ; ▫ réutilisation facilitée ; ▫ testabilité favorisée (grâce à l’isolement et à la possibilité de substituer les implémentations).

17

Les bonnes pratiques dans Spring Décomposition en couches(2/2) Présentation (e.g., JSP, JSF,) Coordination (e.g., Spring MVC, Struts)

Métier (POJO) Accès aux données (e.g., JDBC, Hibernate, JPA) Persistance (e.g.,base de données)

Vue Controlleur Service DAO

Entrepôt de données

18

Les bonnes pratiques dans Spring: Programmation par contrat(1/9) • Principe: consiste à séparer la spécification d'une couche logicielle de sa réalisation. ▫ La spécification donne lieu à la création d'une interface et la réalisation fournit une classe qui implante cette interface. ▫ On peut produire plusieurs implantations différentes d'une même interface.

19

Les bonnes pratiques dans Spring: Programmation par contrat(2/9) • Avantages:

▫ Réduire les dépendances: Les classes d'implantation ne se connaissent pas. Elles dialoguent au moyen des interfaces. De ce fait, on peut facilement changer un implantation contre une autre sans avoir à mettre à jour la totalité du logiciel. ▫ Faciliter les tests: Chaque couche logicielle ayant une spécification claire, il est facile de lui associer un jeu de tests utilisable quelque soit la nature de l'implantation. ▫ Simplifier le code: Dans certains cas de figure, le code d'une méthode est une suite de considérations sans liaison directe entre-elles. La programmation par contrat va faciliter la construction d'implantations façade qui se chargent chacune d'une partie du travail. ▫ Organisation du développement.

20

Les bonnes pratiques dans Spring: Programmation par contrat(3/9) • Exemple: interface IUserDAO{ public void addUser (User user); public User getUserById(Long Id); }

class UserImplJDBC implements IUserDAO{ //add unimplemented method } class UserImplJPA implements IUserDAO{ //add unimplemented method }

21

Les bonnes pratiques dans Spring: Programmation par contrat(4/9) • Avantage majeur: construire des applications faiblement couplées

Couplage faible

Couplage fort

22

Les bonnes pratiques dans Spring Programmation par contrat(5/9) Couplage fort vs couplage faible • Couplage fort: Quand une classe A est lié à une classe B, on dit que la classe A est fortement couplée à la classe B. ▫ La classe A ne peut fonctionner qu’en présence de la classe B. ▫ Si une nouvelle version de la classe B (soit B2), est crée, on est obligé de modifier dans la classe A. ▫ Modifier une classe implique:  Il faut disposer du code source.  Il faut recompiler, déployer et distribuer la nouvelle application aux clients.  Ce qui engendre un cauchemar au niveau de la maintenance de l’application

23

Les bonnes pratiques dans Spring Programmation par contrat(6/9) Couplage fort vs couplage faible • Exemple de couplage fort: Chaque service métier contient des références vers des objets d’accès aux données. UserService

UserDAOImplJPA

Dépendances entre un service métier et un DAO (couplage fort)

24

Les bonnes pratiques dans Spring Programmation par contrat(7/9) Couplage fort vs couplage faible • Couplage faible: consiste à utiliser les interfaces afin de réduire les dépendances entre les classes. • Exemple de couplage faible: ▫ L’introduction d’une interface pour le DAO permet de découpler le service de l’implémentation du DAO. ▫ L’interface définit le contrat de communication, tandis que l’implémentation du DAO le remplit :  le service pourra donc l’utiliser, que la technologie de persistance sousjacente soit JPA ou JDBC.

25

Les bonnes pratiques dans Spring: Programmation par contrat(8/9) Couplage fort vs couplage faible • Exemple de couplage faible UserService

IUserDAO

UserDAOImplJDBC

UserDAOImplJPA

Dépendances entre un service métier et un DAO (couplage faible)

26

Les bonnes pratiques dans Spring: Programmation par contrat(9/9)

Dans une application Spring, l’ensemble des composants (contrôleurs, services et DAO) sont gérés par le conteneur léger.

Communication intercouche par le biais des interfaces

27

Les bonnes pratiques dans Spring: Le singleton (1/2) Le singleton • Il s’agit certainement du patron de conception le plus connu. • En effet, il est (très) utilisé dans beaucoup de domaines. • Ce modèle revient à s’assurer qu’il n’y aura toujours qu’une instance d’une classe donnée qui sera instanciée dans la machine virtuelle. • Les objectifs sont simples : ▫ Eviter le temps d’instanciation de la classe. ▫ Eviter la consommation de mémoire inutile.

• Ce modèle impose cependant une contrainte d’importance, la classe qui fournit le service ne doit pas avoir de notion de session.

28

Les bonnes pratiques dans Spring: Le singleton (2/2) • L’objectif est de garantir l’unicité de l’instance, pour cela il faut interdire la création de toute instance en dehors du contrôle de la classe. • Dans ce but, le constructeur est rendu privé et une méthode qui retourne une instance de la classe est mise à disposition. public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } }

29

Les bonnes pratiques dans Spring: Inversion de contrôle (1/4) • C’est le concept central de spring • Appelé « principe Hollywood » en référence à la phrase mythique « ne nous appelez pas, nous vous appellerons ». • Il s’agit d’un "design pattern" qui a pour objectif de faciliter l’intégration de composants entre eux. • Le concept est basé sur le fait d’inverser la façon dont sont créés les objets.

30

Les bonnes pratiques dans Spring: Inversion de contrôle (2/4) • L’objectif n’est plus de fournir un objet à un autre objet mais au contraire de faire en sorte que, l’objet dont on a besoin, sache lui-même ce dont il a besoin. • Et le cas échéant si un des objets nécessaires a luimême des dépendances qu’il se débrouille pour les obtenir. • La principale forme d’IoC : «l’injection de dépendances» (ou DI)

31

Les bonnes pratiques dans Spring: Inversion de contrôle (3/4) La notion d’injection de dépendance • Principe: s’appuie sur un objet assembleur — le conteneur léger —, capable de gérer le cycle de vie des composants d’une application, ainsi que leurs dépendances, en les injectant de manière appropriée. • Avantages: ▫ Les composants sont plus indépendants de leur environnement d’exécution. ▫ Ils n’ont pas à se soucier de l’instanciation de leurs dépendances et peuvent se concentrer sur leur tâche principale.

32

Les bonnes pratiques dans Spring: Inversion de contrôle (4/4) La notion d’injection de dépendance • Il existe quatre types d’injection : ▫ L’injection par constructeurs: un objet se voit injecter ses dépendances au moment où il est créé, c’est-à dire via les arguments de son constructeur. ▫ L’injection par mutateurs (setters): un objet est créé, puis ses dépendances lui sont injectées par les setters. ▫ L’injection d’interface: un objet est crée puis ses dépendances lui sont injectées par le biais d’une autre méthode => Utiliser une interface pour définir cette méthode d’injection ▫ L’injection par champ : méthode magique de plus en plus populaire

33

Les bonnes pratiques dans Spring: Programmation par aspects(1/4) • Un module ou composant métier est régulièrement pollué par de multiples appels à des composants utilitaires externes.

34

Les bonnes pratiques dans Spring: Programmation par aspects(2/4) • Ceci implique : ▫ ▫ ▫ ▫

Enchevêtrement du code. Faible réutilisabilité. Qualité plus basse due à la complexité du code. Difficulté à faire évoluer.

• Solution: externaliser tous les traitements non relatifs à la logique métier en dehors du composant. • Pour ce faire il faut pouvoir définir des traitements de façon déclarative ou programmative sur les points clés de l’algorithme. ▫ Typiquement avant ou après une méthode.

35

Les bonnes pratiques dans Spring: Programmation par aspects(3/4) • Utilisation de la POA ▫ Les classes pour la logique métier ▫ Les aspects pour les aspects techniques

36

Les bonnes pratiques dans Spring: Programmation par aspects(4/4) • Besoin d’un tisseur d’aspects ▫ par exemple AspectJ pour le langage JAVA

• Rôle: greffer l'ensemble des aspects sur l'ensemble des classes du programme. ▫ Au moment de la compilation ▫ Au moment de l’exécution

37

38

C’est quoi Spring Boot ? • C’est Framework qui a été conçu essentiellement pour développer des architectures à base de microservices ▫ L’idée est de découper une application en petites unités implémentées sous forme de micro-services ▫ Chaque micro-service est responsable d’une fonctionnalité élémentaire, développé, testé et déployé indépendamment des autres ▫ Chaque micro-service peut être conçu à l’aide de n’importe quel langage et technologie =>Couplage faible

39

Avantages de Spring Boot • Faciliter le développement d’applications complexes • Faciliter l’injection des dépendances • Faciliter la gestion des dépendances avec Maven • Réduire les fichiers de configuration et supporter l’auto-configuration • Fournir un conteneur léger embarqué (Tomcat)

40

Création d’un projet Spring Boot

41

Création d’un projet Spring Boot

42

Création d’un projet Spring Boot

43

Structure d’un projet Spring Boot

44

Outils d’intégration continue : Maven ou Gradle • Ces outils jouent un rôle important lors de la gestion et l’automatisation de production des logiciels ▫ ▫ ▫ ▫ ▫ ▫

Gérer les dépendances Lancer la compilation des sources Lancer les tests unitaires Générer les packages (war, jar, ear, etc.) Déployer l’application dans le serveur …

45

Le fichier pom.xml • Voici un extrait du fichier: dependencies>

org.springframework.boot spring-boot-starter-data-jpa

org.springframework.boot spring-boot-starter-web

org.springframework.boot spring-boot-devtools runtime

mysql mysql-connector-java runtime



46

Le fichier Application.properties • Rôle : mettre la configuration des sources de données, serveur, etc. • Exemple: spring.datasource.url=jdbc:mysql://localhost:3306/SpringBoot?server Timezone=UTC spring.datasource.username=root spring.datasource.password= spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver # Hibernate ddl auto (create, create-drop, update) spring.jpa.hibernate.ddl-auto=update # The SQL dialect makes Hibernate generate better SQL for the chosen database spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

47

Le point d’entrée d’une application Spring Boot • Une classe annotée par @SpringBootApplication @SpringBootApplication public class FirstSpringProjectApplication { public static void main(String[] args) { SpringApplication.run(FirstSpringProjectApplication.class, args); } }

• Cette annotation est équivalente à ces 3 annotations ensemble ▫ @EnableAutoConfiguration: activer l’autoconfiguration ▫ @ComponentScan: chercher les beans dans le package de votre application ▫ @Configuration: déclare une classe comme étant une classe de configuration

48

Premier Essai • Créer un projet Spring Boot • Modifier le code comme suit : @SpringBootApplication public class NonWebSpringProjectApplication implements CommandLineRunner{ public static void main(String[] args) { SpringApplication.run(NonWebSpringProjectApplication.class, args); } public void run(String... args) throws Exception { System.out.println("Hello Spring"); } }

• Exécuter l’application comme étant une application JAVA

49

Deuxième Essai • Ajouter cette classe Nom du bean HelloBean

@Component : correspond à l’annotation de base qui signale un composant géré par Spring.

@Component public class HelloBean { public String getMessage(String msg) { return "Hello Spring"+msg; } Nom du bean @Component("monbean") monbean public class HelloBean { } public String getMessage(String msg) { return "Hello Spring"+msg; } }

50

Deuxième Essai • Injection de dépendance du bean HelloBean avec l’annotation @Autowired et appel de méthode dans la classe principale

@SpringBootApplication public class NonWebSpringProjectApplication implements CommandLineRunner{ @Autowired private HelloBean bean;

public static void main(String[] args) { SpringApplication.run(NonWebSpringProjectApplication.class, args); } public void run(String... args) throws Exception { System.out.println(bean.getMessage(" From ENIS Engineer")); } }

51

Troisième Essai • Soit l’exemple suivant: public public public public public public }

interface IMedecinDAO { void addMedecin(Medecin obj); void deleteMedecin(Long id); void updateMedecin(Medecin obj); Medecin findMedecinByID(Long id); List findAll();

public class MedecinDAO implements IMedecinDAO { }

52

Troisième Essai: MedecinDAO @Repository public class MedecinDAO implements IMedecinDAO { @PersistenceContext private EntityManager em; @Transactional public void addMedecin(Medecin obj) { em.persist(obj);} @Transactional public void deleteMedecin(Long id) { em.remove(em.find(Medecin.class, id));} @Transactional public void updateMedecin(Medecin obj) { em.merge(obj);} public Medecin findMedecinByID(Long id) { return em.find(Medecin.class, id);} public List findAll() { Query req= em.createQuery("select m from Medecin m"); return req.getResultList();}}

53

Troisième Essai: classe principale public class FirstSpringProjectApplication implements CommandLineRunner{ @Autowired private IMedecinDAO dao; public static void main(String[] args) { SpringApplication.run(FirstSpringProjectApplication.class, args); } public void run(String... args) throws Exception { dao.addMedecin(new Medecin("Faouzi","Njah",new Date(),"[email protected]",null,"2222" )); Medecin m=dao.findMedecinByID(3L); m.setPrenom("Mariam"); dao.updateMedecin(m); dao.deleteMedecin(2L); } }

54

Une autre façon pour accéder aux données

55

Rappel de notre architecture Back-end

Couche sécurité

Couche d’exposition de services

Couche de services métier

Couche d’accès aux données

DAO Service Spring security

Spring data

RESTful Controller Entities

JPA Hibernate

56

Principe Spring Data (1/4) • Spring Data offre plusieurs interfaces dont les interfaces des Repository peuvent hériter, afin de disposer automatiquement lors de leur génération des implémentations fonctionnelles : ▫ CrudRepository ▫ PagingAndSortingRepository ▫ JpaRepository

57

Principe Spring Data (2/4) • CrudRepository est définie par des templates Generics, prototypant dans sa signature de classe :

▫ La définition d’un Type associé à une classe de modèle (elle même étant par ailleurs une Entity JPA, une classe déclarant @Entity). ▫ Et un type , permettant de définir le type de la clé primaire associée à l’entité, soit un Number (Integer, Long), soit pour une Clé Composée au travers d’une classe dédiée, dans les deux cas, le type est forcément Serializable (contrainte imposée).

• CrudRepository fournit une implémentation standard et par défaut pour les méthodes usuelles suivantes : save, findOne, findAll, count, delete, exists, ... Permettant ainsi de disposer de méthodes principales éprouvées dans le cadre des service DAO (inutile de les ré-implémenter)

58

Principe Spring Data (3/4) • PagingAndSortingRepository Hérite de l’interface CrudRepository, en suivant la même définition de templating Generics, • fournit des méthodes supplémentaires pour le tri findAll(Sort), et la pagination findAll(Pageable).

59

Principe Spring Data (4/4) • JpaRepository Hérite de l’interface PagingAndSortingRepository, en lui ajoutant quelques méthodes spécifiques • Cette interface, la plus avancée, regroupe l’ensemble de toutes les fonctionnalités proposées par Spring Data JPA.

60

Spring Data via l’exemple (1/2) • Pour utiliser Spring Data, il faut declarer springboot-starter-data-jpa comme dépendance dans le pom.xml • Créer pour chaque entité persistante, une interface Héritant de l’interface JpaRepository public interface MedecinRepository extends JpaRepository { }

61

Spring Data via l’exemple (2/2) • On peut spécifier ses propres Query JPQL directement dans le corps de l’interface, en redéfinissant l’implémentation standard par une @nnotation @Query(« select... » ). public interface MedecinRepository extends JpaRepository { @Query("select m from Medecin m where m.nom like :x") public List chercher(@Param("x")String mc); }

62

Rappel de notre architecture Back-end

Couche sécurité

Couche d’exposition de services

Couche de services métier

Couche d’accès aux données

DAO Service Spring security

Spring data

RESTful Controller Entities

JPA Hibernate

63

Implémentation de la couche métier (1/4) • Définir des interfaces contenant la spécification de la partie métier d’une application • Définir des classes implémentant ces interfaces et utilisant l’annotation @Service • Cette annotation est une forme spécialisée de l'annotation @Component destinée à être utilisée dans la couche de service. • Exemple: ▫ Définir l’interface IPatientService ainsi que son implémentation ▫ Définir l’interface IMedecinService ainsi que son implémentation ▫ Définir l’interface IConsultationService ainsi que son implémentation

64

Implémentation de la couche métier (2/4) public interface IPatientService { //Crud Methods public Patient addPatient(Patient p) ; public void deletePatient(Long id) ; public Patient updatePatient(Patient p) ; public Patient findPatient(Long id) ; public List findAll(); //Other methods public MedecinGeneraliste findMG(Long patientID); public Collection findMS(Long patientID); }

@Service @Transactional public class PatientService implements IPatientService { @Autowired PatientRepository patDao;

65

Implémentation de la couche métier (3/4) @Service @Transactional public class PatientService implements IPatientService { @Autowired PatientRepository patDao; public Patient addPatient(Patient p) { return patDao.save(p); } public void deletePatient(Long id) { Optional p= patDao.findById(id); if (p!=null) patDao.delete(p.get()); } public Patient updatePatient(Patient p) { return patDao.save(p); } public Patient findPatient(Long id) { return patDao.getOne(id); }

66

Implémentation de la couche métier (4/4) public List findAll() { return patDao.findAll(); } public MedecinGeneraliste findMG(Long patientID) { Optional p= patDao.findById(patientID); if (p!=null) return p.get().getGeneraliste(); return null; } public Collection findMS(Long patientID) { Optional p= patDao.findById(patientID); if (p!=null) return p.get().getSpecialistes(); return null; } }

67

Rappel de notre architecture Back-end

Couche sécurité

Couche d’exposition de services

Couche de services métier

Couche d’accès aux données

DAO Service Spring security

Spring data

RESTful Controller Entities

JPA Hibernate

68

Implémentation de la couche métier en utilisant des services Web RESTful • Un service Web RESTful est une classe Java décorée par l’annotation @RestController • @RestController est simplement la combinaison des deux annotations: ▫ @Controller de Spring qui permet de désigner une classe comme contrôleur, ayant la capacité de traiter les requêtes de type GET, POST, etc.  Cette annotation peut être utilisée pour identifier les contrôleurs pour Spring MVC

▫ @ResponseBody sera ajouté au niveau des méthodes qui devront répondre directement sans passer par une vue.

69

Implémentation de la couche métier en utilisant des services Web RESTful • Nous allons créer des web services RESTful exposant des API REST gérant les opération CRUD des entités patient, médecin et consultation ▫ PatientRestService.java ▫ MedecinRestService.java ▫ ConsultationRestService.java

• Chaque contrôleur s'occupera de répondre aux requêtes CRUD et de faire les opérations nécessaires.

70

Implémentation de la couche métier en utilisant des services Web RESTful • Nous cherchons à appeler par exemple le microservice gérant les patients sur les URLs suivantes : ▫ Requête GET à /Patients : affiche la liste de tous les patients; ▫ Requête GET à /Patients/{id} : affiche un patient par son Id ; ▫ Requête PUT à /Patients/{id} : met à jour un patient par son Id ; ▫ Requête POST à /Patients : ajoute un patient; ▫ Requête DELETE à /Patients/{id} : supprime un patient par son Id.

71

Implémentation de la couche métier en utilisant des services Web RESTful @RestController public class PatientController { @Autowired PatientRepository pRep; @RequestMapping(value="/patients ", method=RequestMethod.GET) public List findPatients () { return pRep.findAll(); } }

• @RequestMapping permet de faire le lien entre l'URI "/patients", invoquée via GET, et la méthode findPatients() • Cette annotation est utilisée au niveau de la classe et de la méthode. • On peut utiliser à la place @GetMapping

72

Implémentation de la couche métier en utilisant des services Web RESTful @RequestMapping(value="/patients/{id}", method=RequestMethod.GET) public Patient findOnePatient(@PathVariable Long id) { return pRep.findById(id).get(); }

• @PathVariable Cette annotation est utilisée pour annoter les arguments de la méthode du gestionnaire de requêtes. • Cette méthode doit répondre uniquement aux requêtes avec une URI de type /Patients/2 par exemple.

73

Implémentation de la couche métier en utilisant des services Web RESTful • Réponse JSON obtenue

74

Implémentation de la couche métier en utilisant des services Web RESTful @RequestMapping(value="/patients/MG/{id}", method=RequestMethod.GET) public Medecin findMG(@PathVariable Long id) { Chercher le médecin Patient p=pRep.findById(id).get(); généraliste return p.getGeneraliste(); } @PostMapping(value="/Patients") public Patient savePatient(@RequestBody Patient p) { Ajouter return pRep.save(p); }

• @RequestBody Cette annotation demande à Spring que le JSON contenu dans le corps de la requête sera transformé en Objet

75

Implémentation de la couche métier en utilisant des services Web RESTful @RequestMapping(value="/patients/{id}", method=RequestMethod.DELETE) public void deletePatient(@PathVariable Long id) { pRep.deleteById(id); } Supprimer

@RequestMapping(value="/patients/{id}", method=RequestMethod.PUT) public Patient updateContact(@PathVariable(name="id") Long id, @RequestBody Patient p) { p.setId(id); return pRep.save(p); Modifier }

76

77

Introduction • Spring Security est un Framework de sécurité léger qui fournit un support afin de sécuriser les applications Spring. • Il est livré avec des implémentations d’algorithmes de sécurité populaires • Spring Security essaye d’apporter une solution à ces deux problématiques : ▫ l’authentification (savoir qui je suis) ▫ les autorisations (savoir ce que j’ai le droit de faire).

78

Sécurité basique avec Spring security • Afin d’utiliser Spring Security, inclure cette dépendance dans votre fichier Pom.xml

org.springframework.boot spring-boot-starter-security

• Une telle configuration permet d’avoir une sécurité niveau 0 ▫ L’accès aux fonctionnalités du site doivent se faire après une authentification ▫ Pour un utilisateur par défaut « user », le mot de passe est généré d’une manière aléatoire suite à chaque démarrage :

79

Sécurité basique avec Spring security

localhost:8080/patients/1

{"nom": "mohamed", "prenom": "keskes", "dateNaissance": "2018-10-16", "photo": null, "email": "[email protected]", "tel": "2844777", "numCnam": "15588123", "generaliste": { "id": 1, "nom": "Faouzi", "prenom": "Njah", "dateNaissance": "2018-10-16", "email": "[email protected]", "photo": null, "codePublic": "2222" }, "id": 1}

80

Sécurité basique avec Spring security • Le mot de passe qui a été généré peut être modifié via le fichier Application.properties comme suit: spring.security.user.name=user spring.security.user.password=1111

81

Rôles et utilisateurs stockés en mémoire Rôles et utilisateurs stockés en BD

82

Rôles et utilisateurs stockés en mémoire Authentification (1/6) • La première étape est de créer une classe de configuration ▫ Utilisant l’annotation @Configuration ▫ Utilisant aussi l’une de ces annotations  @EnableWebSecurity, et/ou  @EnableGlobalMethodSecurity, et/ou  @EnableGlobalAuthentication.

▫ Tout dépend du niveau de sécurité à activer

83

Rôles et utilisateurs stockés en mémoire Authentification (2/6) • Voici un exemple de bean de configuration @Configuration @EnableWebSecurity public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user").password("{noop}123").roles("USER"); } }

• Le mode d’authentification dans ce code : ▫ chaque user est défini manuellement dans l’application. Par exemple ici seul l’utilisateur "user" avec le rôle "USER" peut s’authentifier.

84

Rôles et utilisateurs stockés en mémoire Authentification (3/6) • Le préfix au niveau de mot de passe {noop} est utilisé pour garder le défaut encoder de Spring Security 5 :NoOpPasswordEncoder ▫ Ce n’est pas une bonne pratique de sauvegarder les mots de passe dans un texte plain ▫ Cet encoder n’est pas sécurisé, utilisé juste pour le test

• Il est préférable d’utiliser l’encoder BCryptPasswordEncoder

85

Rôles et utilisateurs stockés en mémoire Authentification(4/6) • Dans le cas de notre application Web: @Configuration @EnableWebSecurity public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin").password("{noop}1111").roles("ADMIN").and() .withUser("patient").password("{noop}2222").roles("PATIENT").and() .withUser("medecin").password("{noop}3333").roles("MEDECIN"); } }

86

Rôles et utilisateurs stockés en mémoire Authentification(5/6) • Lors du chargement de ce bean, un filtre de servlet (springSecurityFilterChain) est créé. ▫ C’est ce dernier qui orchestrera toute la sécurité  valider si un utilisateur est authentifié ou non  valider si un utilisateur a le droit d’accéder à la ressource ou non  gérer l’authentification et la déconnexion de l’utilisateur  gérer les cas d’erreurs et rediriger l’utilisateur vers les pages d’erreurs

87

Rôles et utilisateurs stockés en mémoire Authentification(6/6) • Il faut absolument définir un et un SEUL AuthenticationManagerBuilder dans l’application. • Cette classe permet de définir quel sera le mode d’authentification des utilisateurs. ▫ inMemoryAuthentication() ▫ jdbcAuthentication()

88

Rôles et utilisateurs stockés en mémoire Autorisations(1/5) • Afin d’ajouter les règles de sécurité et les ressources qu’on veut protéger , il faut redéfinir la méthode suivante @Override protected void configure(HttpSecurity http) throws Exception { // TODO Auto-generated method stub super.configure(http); }

89

Rôles et utilisateurs stockés en mémoire Autorisations : sécuriser les URLs (2/5) • Notre classe de configuration donnée en exemple propose une configuration par défaut qui est la suivante: protected void configure(HttpSecurity http) throws Exception { http 1ére règle de sécurité: .authorizeRequests() Chaque requête doit être authentifiée .anyRequest().authenticated() .and() 2ème règle de sécurité Rediriger la requête vers Login form .formLogin() .and() 3ème règle de sécurité .httpBasic(); }

90

Rôles et utilisateurs stockés en mémoire Autorisations : sécuriser les URLs (3/5) • On peut être moins restrictif ou bien plus restrictif en redéfinissant cette méthode et en la personnalisant selon nos besoins • Exemple: protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/patients/**").hasRole("ADMIN") .and() .formLogin() .defaultSuccessUrl("/patients");; }

91

Rôles et utilisateurs stockés en mémoire Autorisations : sécuriser les méthodes(4/5) • On peut ajouter la sécurité côté méthode • Il faut utiliser l’annotation suivante sur la classe de configuration de Spring security : @EnableGlobalMethodSecurity(securedEnabled = true)

• Il faut aussi utiliser l’annotation @secured au niveau de la méthode comme suit : @Secured ("ROLE_ADMIN" ) public void uneMethodeSecurisee() { // code ne pouvant être exécuté que par un admin }

• N.B: Spring Security ajoute automatiquement le préfixe ROLE_ à n’importe quel rôle

92

Rôles et utilisateurs stockés en mémoire Autorisations: sécuriser les méthodes (5/5) • Exemple : Uniquement l’administrateur a droit à lister tous les patients @RequestMapping(value="/patients",method=RequestMethod.GET) @Secured({"ROLE_ADMIN", "ROLE_MEDECIN"}) public List findPatients () { return pRep.findAll(); }

93

Rôles et utilisateurs stockés en BD User username: String password: String activated:boolean

Role *

* role: String description: String

• Il faut créer ces entités • Créer la couche DAO en implémentant les interfaces UserRepositoy et RoleRepository • Remplir les tables en définissant par exemple 3 utilisateurs : un administrateur, un patient et un médecin • Vous pouvez ajouter un service Rest pour gérer les utilisateurs et les rôles

94

Rôles et utilisateurs stockés en BD Création des entités USER et ROLE @Entity public class User implements Serializable { @Id private String username; private String password; private boolean actived; @ManyToMany private Collection roles; // Getters, setters and constructors } @Entity public class Role implements Serializable { @Id private String role; private String description; //Getters, setters and constructors }

95

Rôles et utilisateurs stockés en BD Création des repositories public interface UserRepository extends JpaRepository { }

public interface RoleRepository extends JpaRepository {

}

96

Rôles et utilisateurs stockés en BD Définition des utilisateurs et des rôles @Autowired RoleRepository roleRepository; public static void main(String[] args) { SpringApplication.run(MyWebProjectApplication.class, args); } public void run(String... args) throws Exception { //insertion des rôles de l'application Role admin= new Role("ADMIN", "administrateur"); Role patient= new Role("PATIENT", "patient"); Role medecin= new Role("MEDECIN", "medecin"); roleRepository.save(admin); roleRepository.save(patient); roleRepository.save(medecin); }

97

Rôles et utilisateurs stockés en BD Définition des utilisateurs et des rôles //insertion de 3 utilisateurs User adminUser= new User("admin", "1111", true); Collection lst= new ArrayList(); lst.add(roleRepository.findById("ADMIN").get()); adminUser.setRoles(lst); userRepository.save(adminUser); User pUser= new User("patient1", "p2222", true); Collection lst1= new ArrayList(); lst1.add(roleRepository.findById("PATIENT").get()); pUser.setRoles(lst1); userRepository.save(pUser);

User mUser= new User("medecin1", "m2222", true); Collection lst2= new ArrayList(); lst2.add(roleRepository.findById("MEDECIN").get()); mUser.setRoles(lst2); userRepository.save(mUser);

98

Rôles et utilisateurs stockés en BD Authentification @Autowired public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception { auth.jdbcAuthentication() .dataSource(dataSource) .usersByUsernameQuery("select username as principal, password as credentials, true from user where username=?") .authoritiesByUsernameQuery("select user_username as principal, roles_role as role from user_roles where user_username=?") .rolePrefix("ROLE_"); }

• Ces 2 requêtes sont utilisées par Spring Security pour ▫ Récupérer l’utilisateur et vérifier son existence et son mot de passe ▫ Récupérer le(s) rôle(s) de cet utilisateur

99

Rôles et utilisateurs stockés en BD Password Encoder • Préciser l’encoder de mot de passe dans la classe de configuration de Spring Security @Bean public PasswordEncoder passwordEncoder(){ PasswordEncoder encoder = new BCryptPasswordEncoder(); return encoder; }

• Ceci suppose que le mot de passe a été inséré dans la base de données crypté String password = passwordEncoder().encode("0000"); User adminUser= new User("superadmin", password, true); Collection lst= new ArrayList(); lst.add(roleRepository.findById("ADMIN").get()); adminUser.setRoles(lst); userRepository.save(adminUser);

100

Approfondissement • Tutoriel sur Spring security et JWT (Json Web Tokens) • https://www.youtube.com/watch?v=1BlJeuQ4dk&list=PLI4OjXANJOaFv4XCI1wwO7ZDURpN I18Iu

101

Failles de sécurité Cross Site Request Forgery (CRSF) • Un type de vulnérabilité des services d’authentification Web • Cette attaque permet de transmettre à un utilisateur authentifié • Une requête HTTP falsifiée qui pointe sur une action interne au site • Afin qu’il exécute sans en avoir conscience et en utilisant ses propres droits • L’utilisateur devient donc complice d’une attaque sans s’en rendre compte