Introduction au système
Ce système de livraison de repas est développé avec une architecture moderne, utilisant SpringBoot pour le backend et Vue pour le frontend, avec MyBatis-Plus comme couche de persistance pour une gestion efficace des données.
Pile technologique
Backend : SpringBoot
SpringBoot simplifie le développement d'applications Java en intégrant des serveurs embarqués comme Tomcat et en offrant une configuration automatique basée sur les dépendances du projet. Il fournit des fonctionnalités prêtes à l'emploi telles que Spring Data, Spring Security et Spring Cloud, permettant une construction rapide et extensible d'applications robustes.
Frontend : Vue
Vue.js exploite le virtual DOM pour des mises à jour efficaces de l'interface utilisateur, grâce à une liaison de données réactive et une architecture par composants. Cette approche permet aux développeurs de se concentrer sur la logique métier sans gérer manuellement les manipulations du DOM, offrant ainsi flexibilité et performance.
Persistance : MyBatis-Plus
MyBatis-Plus étend les capacités de MyBatis en réduisant le besoin de code SQL manuel. Il supporte plusieurs bases de données, propose des annotations et API riches, et inclut un générateur de code pour créer automatiquement les entités, interfaces Mapper et fichiers de mapping. Des fonctionnalités comme la pagination, les requêtes dynamiques et l'optimistic locking améliorent l'efficacité des opérations sur les données.
Test du système
Objectifs des tests
Les tests visent à identifire les défauts du système en simulant des scénarios d'utilisation réels, en s'assurant que les fonctionnalités répondent aux exigences et en améliorant l'expérience utilisateur. Une approche de boîte noire est employée pour vérifier la conformité aux spécifications sans examiner le code interne.
Tests fonctionnels
Des cas de test sont conçus pour des modules clés comme l'authentification et la gestion des utilisateurs. Par exemple, pour l'authentification :
| Entrée | Résultat attendu | Résultat obtenu | Analyse |
|---|---|---|---|
| Nom d'utilisateur : admin, Mot de passe : secret, Captcha : correct | Connexion réussie | Connexion réussie | Conforme aux attentes |
| Nom d'utilisateur : admin, Mot de pase : incorrect, Captcha : correct | Erreur de mot de passe | Erreur de mot de passe | Conforme aux attentes |
| Nom d'utilisateur : vide, Mot de passe : secret, Captcha : correct | Champ nom d'utilisateur requis | Champ nom d'utilisateur requis | Conforme aux attentes |
Pour la gestion des utilisateurs, les tests incluent l'ajout, la modification et la supression avec validation des champs obligatoires et des contraintes d'unicité.
Conclusion des tests
Après une série de tests, le système démontre une conformité fonctionnelle et des performances satisfaisantes, confirmant sa fiabilité et son adéquation aux besoins utilisateurs.
Exemples de code
Méthode d'authentification
@IgnoreAuth
@PostMapping(value = "/authentification")
public Response authentifierUtilisateur(String identifiant, String motDePasse, String codeVerification, HttpServletRequest requete) {
UtilisateurEntity utilisateur = serviceUtilisateur.rechercherParIdentifiant(identifiant);
if (utilisateur == null || !utilisateur.getMotDePasse().equals(motDePasse)) {
return Response.erreur("Identifiants invalides");
}
String jetonAcces = serviceJeton.creerJeton(utilisateur.getId(), identifiant, "utilisateurs", utilisateur.getRole());
return Response.succes().avec("jeton", jetonAcces);
}
Génération de jeton d'accès
@Override
public String creerJeton(Long idUtilisateur, String identifiant, String tableReference, String role) {
JetonEntity jetonExistant = rechercherJetonParUtilisateur(idUtilisateur, role);
String nouveauJeton = GenerateurAleatoire.creerChaine(32);
Date expiration = calculerExpiration(1);
if (jetonExistant != null) {
jetonExistant.setJeton(nouveauJeton);
jetonExistant.setDateExpiration(expiration);
mettreAJourJeton(jetonExistant);
} else {
insererJeton(new JetonEntity(idUtilisateur, identifiant, tableReference, role, nouveauJeton, expiration));
}
return nouveauJeton;
}
Intercepteur d'autorisation
@Component
public class IntercepteurAutorisation implements HandlerInterceptor {
private static final String CLE_JETON = "JetonAcces";
@Autowired
private ServiceJeton serviceJeton;
@Override
public boolean preHandle(HttpServletRequest requete, HttpServletResponse reponse, Object handler) throws Exception {
configurerEnTetesCORS(reponse);
if (requete.getMethod().equals(RequestMethod.OPTIONS.name())) {
reponse.setStatus(HttpStatus.OK.value());
return false;
}
if (estAnnotationIgnoreAuth(handler)) {
return true;
}
String jeton = requete.getHeader(CLE_JETON);
JetonEntity jetonValide = validerJeton(jeton);
if (jetonValide != null) {
requete.getSession().setAttribute("idUtilisateur", jetonValide.getIdUtilisateur());
requete.getSession().setAttribute("role", jetonValide.getRole());
return true;
}
envoyerReponseErreur(reponse, 401, "Authentification requise");
return false;
}
}
Référence de base de données
Structure de la table des jetons d'authentification :
DROP TABLE IF EXISTS `jetons_acces`;
CREATE TABLE `jetons_acces` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'Clé primaire',
`id_utilisateur` BIGINT(20) NOT NULL COMMENT 'ID utilisateur',
`nom_utilisateur` VARCHAR(100) NOT NULL COMMENT 'Nom d\\'utilisateur',
`table_ref` VARCHAR(100) DEFAULT NULL COMMENT 'Table associée',
`role` VARCHAR(100) DEFAULT NULL COMMENT 'Rôle',
`jeton` VARCHAR(200) NOT NULL COMMENT 'Jeton d\\'accès',
`date_creation` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Date de création',
`date_expiration` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date d\\'expiration',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Table des jetons d\\'accès';