IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Formulaire login/mot de passe et gestion des utilisateurs pour une application liée à une base de données

Ce tutoriel propose une solution d'identification-authentification développée avec Lazarus pour une application fonctionnant sous Windows. L'application qui permet aussi le changement de mot de passe ainsi que la gestion des utilisateurs est liée à une base de données sans pour autant en être l'administratrice. Cependant, la base devient aussi le lieu de stockage des identifiants et des mots de passe.

2 commentaires Donner une note  l'article (5)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Débutant : avant de passer à ce tutoriel, il est préférable d’étudier le tutoriel « Gestion d'une base de données MySQL » d’Alcatiz.

https://alcatiz.developpez.com/tutoriel/lazarus-mysql/

Ce tutoriel destiné initialement à élaborer un formulaire de connexion par mot de passe pour limiter et sécuriser l’accès à une application liée à une base de données, vous amènera à lui associer d'autres formulaires et à rendre l'accès à l'application encore plus sûr. Il vous est proposé de créer une application factice dont vous pourrez réutiliser les codes dans vos propres créations. Ici, ne seront pas reprises les premières étapes de création d’une application avec Lazarus.

Ce tutoriel est inspiré de celui pour Microsoft Access, « Comment concevoir un formulaire login/mot de passe ? » réalisé par Morsi, ainsi que de celui de Denis Hulo, « Créer une gestion des droits des utilisateurs avec Access ».

https://access.developpez.com/faq/?page=TAAdmin#login

https://denishulo.developpez.com/tutoriels/access/gestion-droits-utilisateurs/

Le choix s’est porté sur une base de données de type MariaDB administrée avec phpMyAdmin.

Pour que l’application fonctionne, il faut que le serveur et la base de données soient actifs.

Pour utiliser MariaDB, il est nécessaire de mettre le fichier libmysql.dll dans le dossier contenant l’application. Il faut aussi utiliser le composant TmySQLxxConnection adapté à la version de MariaDB ainsi que bien renseigner le port.

Comme stipulé dans la publication de Morsi, un formulaire login/mot de passe permet à un utilisateur de s'identifier et à la base de le reconnaître et de décider de lui donner ou non la permission d'accéder aux données.

Donc, nous créerons un formulaire de connexion « login/mot de passe » pour sécuriser l'accès à l'application. Ensuite, nous réaliserons aussi un formulaire permettant aux utilisateurs de changer leur mot de passe comme cela est souvent demandé de le faire lors d'une première connexion. Enfin, nous irons un peu plus loin en élaborant un formulaire de gestion des utilisateurs de l'application. Avec celui-ci, un administrateur pourra inscrire des utilisateurs ou bien en supprimer. Mais avant tout, commençons par nous occuper de la base de données.

II. La base de données

Au niveau de la base de données, il faut créer la table t_user avec les colonnes : id, trigramme, nom, prenom, groupe, paswd. Tous les champs sont de type « VARCHAR » sauf id qui est de type « INT ».

Exemple d’enregistrement dans cette table : « ‘1’,‘gdéon’,‘DEON’,‘Gérard’,‘Util’, ‘GlaCléde12!’ ».

Code SQL pour créer la table :

 
Sélectionnez
CREATE TABLE `t_user` (
        `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        `trigramme` VARCHAR(20) NOT NULL,
        `nom` VARCHAR(20) NOT NULL,
        `prenom` VARCHAR(20) NOT NULL,
        `groupe` VARCHAR(20) NOT NULL,
         `paswd` VARCHAR(20) NOT NULL,
        PRIMARY KEY (`id`)
)
COLLATE='latin1_general_cs';

III. Création des unités et des fiches

Après avoir enregistré le projet, nous passons à la création des unités et des fiches (formes) :

  • Data et l'unité datamodule pour la fiche de liaison à la base de données ;
  • FormLogin et l'unité login pour le formulaire de connexion ;
  • FormMain et l'unité main pour la fiche support de l'application ;
  • FormChgt et l'unité chgtmdp pour le formulaire de changement de mot de passe ;
  • FormGutil et l'unité gutil pour le formulaire de gestion des utilisateurs.

Pour Data, il faut créer un datamodule et pas une fiche classique.

IV. Composants et aménagement des formulaires et fiches

Dans ce chapitre, nous constituons chaque formulaire et fiche avec les composants nécessaires. Nous procédons à leur disposition et nous paramétrons certaines de leurs propriétés.

IV-A. La fiche Data

Image non disponible

Composants

Propriétés

TData

Name : Data

TMySQL56Connection

DatabaseName : Nom de la base
Name : SQLConnect
Password : Mot de passe
Port : (en fonction de MariaDB)
Transaction : SQLTransact
UserName : Nom d'utilisateur de la base
HostName : Nom d'hôte

TSQLTransaction

Database : SQLConnect
Name : SQLTransact

TSQLQuery

Database : SQLConnect
Name : SQLreqMDP
Transaction : SQLTransact

TSQLQuery

Database : SQLConnect
Name : SQLreqNMDP
Transaction : SQLTransact

TSQLQuery

Database : SQLConnect
Name : SQLreqGutil
Transaction : SQLTransact

IV-B. Le formulaire de connexion

Image non disponible

Composants

Propriétés

TForm

BorderStyle :bsToolWindow
Caption : Connexion
Color : clActiveCaption
Name : FormLogin
Position : poScreenCenter

TButton

Caption : Entrer
Name : BtnEntr

TButton

Caption : Annuler
Name : BtnAnnul1

TEdit

MaxLength : 20
Name : EdMdp1
Text : Effacer le contenu
PasswordChar : *

TLabel

Caption : Identifiant
Name : LbIdent

Tlabel

AutoSize : False
Caption : Effacer le contenu
Color : clWhite et Ajuster la position et la taille du composant
Name : LbUser
Transparent : False

TLabel

Caption : Mot de passe
Name : LbMdp

TLabel

Caption : 3 essais maximum
Name : LbEss

IV-C. La fiche de l'application

Image non disponible

Composants

Propriétés

TForm

Caption : MDPtuto (à vous de choisir)
Name : FormMain
Position : poScreenCenter

TLabel

Caption : Changement mot de passe
Font → Style → fsUnderline : (True)
Name : LbChgt

TLabel

Caption : Gestion des utilisateurs
Font → Style → fsUnderline : (True)
Name : LbGest

IV-D. Le formulaire de changement de mot de passe

Image non disponible

Composants

Propriétés

TForm

BorderStyle : bsToolWindow
Caption : Changement mot de passe
Color : clActiveCaption
Name : FormChgt
Position : poScreenCenter

TButton

Caption : Valider
Name : BtnValid

TButton

Caption : Annuler
Name : BtnAnnul2

TEdit

Name : EdNmdp
Text : Effacer le contenu
PasswordChar : *

TEdit

Name : EdConf
Text : Effacer le contenu
PasswordChar : *

TLabel

Caption : Nouveau mot de passe
Name : LbNmdp

TLabel

Caption : Confirmation mot de passe
Name : LbConf

IV-E. Le formulaire de gestion des utilisateurs

Image non disponible

Composants

Propriétés

Tform

Caption : Gestion des utilisateurs
Color : clActiveCaption
Name : FormGutil
Position : poScreenCenter

TButton

Caption : Créer
Name : BtnCrea

TButton

Caption : Supprimer
Name : BtnSup

TButton

Caption : Annuler
Name : BtnAnnul3

TEdit

Name : EdIdentU
Text : Effacer le contenu

TEdit

Name : EdNomU
Text : Effacer le contenu

TEdit

Name : EdPrenU
Text : Effacer le contenu

TEdit

Name : EdMdpU
Text : Effacer le contenu

TComboBox

Item: Admin
Util
Name : ComboGpe
Style : csDropDownList
Text : Effacer le contenu

TLabel

Caption : Identifiant util
Name : LbIdentU

TLabel

Caption : Nom util *
Name : LbNomU

TLabel

Caption : Prénom util *
Name : LbPrenU

TLabel

Caption : Groupe util
Name : LbGpeU

TLabel

Caption : Mot de passe util *
Name : LbMdpU

TLabel

Caption : (* Non nécessaire pour supprimer)
Name : LbInfoSup

V. Le code

Les fiches prêtes avec leurs composants paramétrés, nous passons maintenant au code. Nous commençons par l'ordonnancement des fiches, puis nous nous attaquerons à l'élaboration du code de chacune d'elles.

Il faudra penser à mettre Dialogs dans les clauses uses des unités où sera utilisé ShowMessage et en plus LCLType où sera utilisé MessageBox.

V-A. Ordonnancement des fiches

Comme le veut une bonne pratique, nous ne chargeons pas toutes les fiches au démarrage de l'application. Donc, nous allons les ordonner en affichant dans Lazarus le code source en cliquant sur Projet et ensuite Voir le code source. Nous le modifions pour que ce soit le formulaire de connexion FormLogin qui apparaisse le premier au lancement de l'application. Les autres fiches ne seront pas chargées d'emblée, exceptée Data. Dans le respect de la logique de connexion préalable à la base de données, Data sera créée avant FormLogin.

 
Sélectionnez
program MDPtuto;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, main, datamodule, login, chgtmdp, gutil, lazdbexport;

{$R *.res}

begin
  RequireDerivedFormResource:= True;
  Application.Title:= 'MDPtuto';
  Application.Scaled:= True;
  Application.Initialize;
  Application.CreateForm(TData,Data);
  FormLogin:= TFormLogin.Create(Application);
    if FormLogin.ShowModal= 1 then
  Application.Run
    else
  Formlogin.Close; //Libération pour éviter les fuites de mémoire
end.

V-B. Le code de la fiche Data

La fiche Data constitue une véritable « interface » entre l'application, ses formulaires et la base de données. Le code concernant cette fiche est créé dans l'unité datamodule. Nous allons préparer l'unité pour accueillir les procédures et fonctions au fur et à mesure de la construction des formulaires.

Nous déclarons les variables et les fonctions qui seront utilisées pour la connexion, le changement de mot de passe et la gestion des utilisateurs.

 
Sélectionnez
  public
    User: String;
    gpe: String;
    function Connexion(cMdp: String): boolean;
    function Testmdp(cNmdp: String): boolean;
    function Testgpu(cutil,cgpu: String): boolean;
    function Testmdpu(cutil,cmdpu: String): boolean;
    function Changement(cNmdp: String): boolean;
    function Creatutil(cutil,cnomu,cprenu,cgpu,cmdpu: String): boolean;
    function Suputil(cutil,cgpu: String): boolean;

Pour pouvoir procéder par la suite à l'identification-authentification de l'utilisateur, nous devons préalablement récupérer son identifiant de session.

 
Sélectionnez
procedure TData.DataModuleCreate(Sender: TObject);
begin
  User:= Application.EnvironmentVariable['USERNAME']; //Récupération de l'identifiant utilisateur
end;

V-C. Le code du formulaire de connexion

La fiche FormLogin constitue le formulaire qui permet de se connecter à l'application via une identification-authentification par identifiant et mot de passe en lien avec la table t_user. Pour plus de sécurité, à la troisième tentative de connexion erronée l'application se ferme. Le mot de passe pouvant être saisi dans le champ dédié doit être composé de 20 caractères maximum. Le code concernant ce formulaire est créé dans l'unité login.

Cette fiche doit être liée à la base de données grâce à Data et à FormMain pour l'application. Donc, nous déclarons les clauses uses comme suit :

 
Sélectionnez
implementation

{$R *.lfm}

uses
  datamodule, main;

Pour procéder à l'identification-authentification, la connexion nécessite l'identifiant de session de l'utilisateur du PC. Sa récupération étant faite au niveau du datamodule, son affichage se fait avec le composant LbUser dans le formulaire dès sa création.

 
Sélectionnez
procedure TFormLogin.FormCreate(Sender: TObject); //Récupération des éléments d'identification-authentification
begin
  LbUser.Caption:= Data.User; //Recueil de l'identifiant utilisateur
end;

Pour compter les tentatives de connexion nous devons élaborer la procédure Tentative que nous déclarons comme suit :

 
Sélectionnez
  TFormLogin = class(TForm)
    BtnEntr: TButton;
    BtnAnnul1: TButton;
    EdMdp: TEdit;
    LbEss: TLabel;
    LbMdp: TLabel;
    LbUser: TLabel;
    LbIdent: TLabel;
    procedure BtnAnnul1Click(Sender: TObject);
    procedure BtnEntrClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure Tentative(tentatives: word);

Puis nous déclarons la variable tentatives qui sera utilisée dans la procédure de comptage et de qualification des tentatives de connexion et Mdp dans la fonction de connexion.

 
Sélectionnez
  private
    tentatives: word;
    Mdp: String;

Nous pouvons maintenant construire la procédure Tentative qui comptera et qualifiera les tentatives de connexion. Cette procédure impose qu'après la troisième tentative erronée, le formulaire de connexion se ferme ainsi que l'application.

 
Sélectionnez
procedure TFormLogin.Tentative(tentatives: word); //Procédure de comptage des tentatives de connexion
begin
  case tentatives of
  0 : ShowMessage('Erreur de mot de passe. Deuxième essai.'); //Info 2e essai
  1 : ShowMessage('Erreur de mot de passe. Attention ! Dernier essai.'); //Info dernier essai
  2 : FormLogin.Close; //Ferme le formulaire de connexion
  end;
end;

L'identification-authentification se fait par un clic sur le bouton Entrer qui appelle la fonction de connexion que nous élaborerons dans l'unité datamodule. C'est également à ce niveau que le mot de passe de l'utilisateur est récupéré. Le clic sur le bouton appelle aussi l'incrémentation des tentatives de connexion quand il y a une erreur.

 
Sélectionnez
procedure TFormLogin.BtnEntrClick(Sender: TObject); //Connexion
begin
  Mdp:= EdMdp.Text; //Récupération mot de passe
  if Data.Connexion(Mdp)= True then //Appel fonction de connexion
    begin
      FormMain:= TFormMain.Create(Application); //Création de la forme de l'application
      FormMain.Show; //Montre la forme de l'application
      FormLogin.Hide; //Cache le formulaire de connexion
    end
  else
  FormLogin.Tentative(tentatives); //Appel procédure comptage des tentatives de connexion
  inc(tentatives); //Incrémentation des tentatives de connexion
end;

Quand il y a une erreur de mot de passe, un message apparaît. Quand l'utilisateur clique sur OK ou ferme le message, il revient au formulaire de connexion pour modifier la saisie du mot de passe et essayer à nouveau de se connecter. Voici les messages :

Image non disponible

Image non disponible

Le bouton Annuler annule et ferme le formulaire de connexion. La fermeture du formulaire par le bouton Annuler ou par la croix X provoque la fermeture de l'application.

 
Sélectionnez
procedure TFormLogin.BtnAnnul1Click(Sender: TObject); //Annulation de la connexion
begin
  Close;
end;

À la fermeture du formulaire, nous libérons la mémoire.

 
Sélectionnez
procedure TFormLogin.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  CloseAction:= caFree; //Libère la mémoire
end;

Au niveau de l'unité datamodule, nous construisons la fonction Connexion qui interroge la base de données pour y rechercher l'utilisateur et lui ouvrir l'application. Nous profitons de la connexion pour récupérer le groupe d'appartenance de l'utilisateur lié au mot de passe. Ceci sera déterminant pour donner l'accès ou non au formulaire de gestion des utilisateurs. Si son statut d'utilisateur est administrateur « Admin », il y aura accès contrairement à un simple utilisateur « Util ».

 
Sélectionnez
function TData.Connexion(cMdp: String): boolean; //Fonction de connexion
begin
  //Test de présence de l'utilisateur dans la table t_user selon son mot de passe
  result:= False;
  SQLreqMDP.Close;
  SQLreqMDP.SQL.Text:='SELECT trigramme,paswd,groupe FROM t_user WHERE trigramme =:t AND paswd =:m;';
  SQLreqMDP.ParamByName('t').asString:= User;
  SQLreqMDP.ParamByName('m').asString:= cMdp;
  SQLreqMDP.Open;
    if SQLreqMDP.FieldBYName('groupe').asString <> '' then
  result:= True; //Utilisateur présent
  gpe:= SQLreqMDP.FieldBYName('groupe').asString; //Récupération du statut de l'utilisateur
end;

V-D. Le code de l'application

La fiche FormMain constitue le support de l'application. L'application est appelée depuis le formulaire de connexion après identification-authentification. Le code concernant l'application est créé dans l'unité main.

Depuis la fiche FormMain sont appelés les formulaires de changement de mot de passe et de gestion des utilisateurs. Cette fiche doit être liée à ces formulaires, mais aussi avec Data. Donc nous déclarons les clauses uses comme suit :

 
Sélectionnez
implementation

{$R *.lfm}

uses
  datamodule, chgtmdp, gutil;

L'appel du formulaire de changement de mot de passe FormChgt se fait par un clic sur le composant LbChgt (Changement mot de passe) qui ouvre une boîte message énonçant les règles de composition d'un mot de passe. Elle donne le choix d'accéder au formulaire de changement de mot de passe (clic sur OK) ou de retourner à l'application (clic sur Cancel).

 
Sélectionnez
procedure TFormMain.LbChgtClick(Sender: TObject); //Montre le message de composition des mots de passe
var
  reply: integer;
  boxstyle: integer;
begin
    with application do
    begin
      boxstyle:= MB_ICONINFORMATION + MB_OKCANCEL;
      reply:= MessageBox('Pour être valide, le nouveau mot de passe doit avoir une longueur comprise entre 8 et 20 caractères. Il doit obligatoirement contenir une majuscule, une minuscule, un chiffre et un caractère spécial.', 'Règles de composition du mot de passe', boxstyle);
        if reply = IDOK then
      begin
        FormChgt:= TFormChgt.Create(Application); //Création du formulaire de changement de mot de passe
        FormChgt.ShowModal; //Montre le formulaire
      end
        else
      FormMain.Show; //Retourne à l'application
    end;
end;

Voici le message préalable à l'accès au formulaire de changement de mot de passe :

Image non disponible

L'appel du formulaire de gestion des utilisateurs FormGutil se fait par un clic sur le composant LbGest (Gestion des utilisateurs). L'ouverture du formulaire est conditionnée par l'appartenance de l'utilisateur au groupe administrateur « Admin ». Cette condition est recherchée au niveau de la fonction Connexion dans l'unité datamodule. C'est lors de l'utilisation de celle-ci qu'est récupéré le groupe (statut) dans lequel ce dernier est inscrit.

 
Sélectionnez
procedure TFormMain.LbGestClick(Sender: TObject); //Ouvre le formulaire de gestion des utilisateurs
begin
    if Data.gpe <> 'Admin' then
  ShowMessage('Vous ne possédez pas les droits pour cette fonctionnalité.')
    else
  begin
    FormGutil:= TFormGutil.Create(Application); //Création du formulaire de gestion des utilisateurs
    FormGutil.ShowModal; //Montre le formulaire 
  end;
end;

Si l'utilisateur n'a pas les droits d'administrateur pour accéder au formulaire de gestion des utilisateurs, un message l'avertit. À la fermeture du message, l'utilisateur revient à l'application.

Image non disponible

Pour fermer l'application, en cliquant sur la croix X, nous utilisons le code classique suivant :

 
Sélectionnez
procedure TFormMain.FormClose(Sender: TObject; var CloseAction: TCloseAction); //Fermeture de l'application
begin
  Application.Terminate;
end;

V-E. Le code du formulaire de changement de mot de passe

La fiche FormChgt constitue le formulaire qui permet à un utilisateur de changer son mot de passe. Ce formulaire est appelé depuis l'application. Dans celui-ci, l'utilisateur doit saisir son nouveau mot de passe en respectant des règles strictes de saisie et le confirmer. Ce mot de passe doit être composé de 8 à 20 caractères, dont au moins une majuscule, une minuscule, un chiffre et un caractère spécial. Le code concernant ce formulaire est créé dans l'unité chgtmdp.

Nous déclarons la variable Nmdp qui sera utilisée dans la fonction de changement de mot de passe ainsi que les fonctions Testchamp et Testchar qui vérifieront la conformité de celui-ci. Nous déclarons aussi la procédure Procrazchgt que nous utiliserons pour effacer les champs de saisie du formulaire.

 
Sélectionnez
  private
    Nmdp: String;
    function Testchamp(cNmdp: String): boolean;
    function Testchar(cNmdp: String): boolean;
    procedure Procrazchgt(Form: TForm);

Nous déclarons les clauses uses qui permettront de lier le formulaire de changement de mot de passe à celui de connexion et à Data ainsi qu'à RegExpr qui permet la vérification de la composition du nouveau mot de passe en termes de types de caractères.

 
Sélectionnez
implementation

{$R *.lfm}

uses
  login, datamodule, RegExpr;

Nous élaborons la procédure d'effacement des champs de saisie du formulaire constitués par les composants EdNmdp et EdConf.

 
Sélectionnez
procedure TFormChgt.Procrazchgt(Form: TForm); //Procédure d'effacement du contenu des champs du formulaire
var
  I: Integer;
begin
  for I:= 0 to Form.ComponentCount - 1 do
    if Form.Components[I] is TEdit then
  TEdit(Form.Components[I]).Text:= '';
end;

Nous créons la fonction Testchamp qui vérifiera la complétude des champs de saisie du nouveau mot de passe et de sa confirmation selon les critères de présence, de taille, mais aussi de différence avec celui jusqu'alors employé par l'utilisateur. Cette fonction sera utilisée dans la procédure de validation du changement de mot de passe.

 
Sélectionnez
function TFormChgt.Testchamp(cNmdp: String): boolean; //Fonction de vérification du contenu des champs
begin
  result:= False;
    if cNmdp = '' then
  ShowMessage('Absence de nouveau mot de passe.')
    else
    if EdConf.Text = '' then
  ShowMessage('Absence de confirmation du mot de passe.')
    else
    if cNmdp <> EdConf.Text then
  ShowMessage('Mot de passe et confirmation différents.')
    else
    if Length(cNmdp) < 8 then
  ShowMessage('Longueur minimale du mot de passe non conforme.')
    else
    if Length(cNmdp) > 20 then
  ShowMessage('Longueur maximale du mot de passe non conforme.')
    else
    if cNmdp = FormLogin.EdMdp.Text then
  ShowMessage('Mot de passe identique à celui utilisé précédemment.')
    else
  result:= True;
  end;

Nous construisons ensuite la fonction Testchar qui permettra de s'assurer de la composition en termes de majuscule, de minuscule, de chiffre et de caractère spécial du nouveau mot de passe saisi par l'utilisateur. Comme la fonction précédente, elle sera également utilisée dans la procédure de validation du changement de mot de passe.

 
Sélectionnez
function TFormChgt.Testchar(cNmdp: String): boolean; //Fonction de vérification des caractères du nouveau mot de passe
var
  Expr: TRegExpr;
  const spchar = ',;:!§£€$~#{|`^@{}_&é"èçà<>%ù²'; //Caractères spéciaux
  const escspchar = '\.\?\=\[\]\+\-\*\(\)'; //Autres caractères spéciaux
begin
  result:= False;
  Expr:=TRegExpr.Create;
  Expr.Expression := '[A-Z]+';
    if not Expr.Exec(cNmdp) then //Absence de majuscule
  begin
    ShowMessage('Absence de majuscule.');
    exit;
  end
    else
  Expr.Expression := '[a-z]+';
    if not Expr.Exec(cNmdp) then //Absence de minuscule
  begin
    ShowMessage('Absence de minuscule.');
    exit;
  end
    else
  Expr.Expression := '\d+';
    if not Expr.Exec(cNmdp) then //Absence de chiffre
  begin
    ShowMessage('Absence de chiffre.');
    exit;
  end
    else
  Expr.Expression := '['+spchar+escspchar+']+';
    if not Expr.Exec(cNmdp) then //Absence de caractère spécial
  begin
    ShowMessage('Absence de caractère spécial.');
    exit;
  end
    else
  result:= True; //Conformité de types de caractères dans le nouveau mot de passe
end;

La fonction de changement de mot de passe est appelée par le bouton Valider. La validation passe préalablement par la série de contrôles définis dans les fonctions Testchamp, Testchar et Testmdp. Ces tests passés avec succès, le changement peut être lancé. Le test de mot de passe non identique à celui d'un autre compte de l'utilisateur fait l'objet de la fonction Testmdp que nous élaborerons dans l'unité datamodule.

 
Sélectionnez
procedure TFormChgt.BtnValidClick(Sender: TObject); //Appel changement de mot de passe
begin
  Nmdp:= EdNmdp.Text;
    if (Testchamp(Nmdp)= False) or (Testchar(Nmdp)= False) then
    exit;
    if Data.Testmdp(Nmdp)= False then //Teste si le mot de passe est non identique à celui d'un autre compte de l'utilisateur
  ShowMessage('Mot de passe déjà utilisé dans un de vos profils.')
    else
    if Data.Changement(Nmdp)= True then //Appel conditionnel de la fonction de changement de mot de passe
  begin
    ShowMessage('Changement de mot de passe réussi.');
    FormChgt.Close; //Ferme le formulaire quand changement réussi
  end;
end;

Pour chaque problème de conformité de complétude des champs, un message informe l'utilisateur. Le message correspond à la première erreur rencontrée à chaque tentative de validation. À la fermeture, l'utilisateur se retrouve de nouveau sur le formulaire pour corriger ou renoncer à son changement de mot de passe. Exemple de message d'erreur :

Image non disponible

De même, pour chaque problème de conformité de la composition du nouveau mot de passe, un message informe l'utilisateur. Le message correspond à la première erreur rencontrée à chaque tentative de validation. À la fermeture, l'utilisateur se retrouve de nouveau sur le formulaire pour corriger ou renoncer à son changement de mot de passe. Exemple de message d'erreur :

Image non disponible

Si le nouveau mot de passe est identique à celui d'un autre de ses profils, un message prévient l'utilisateur. À la fermeture, il est ramené au formulaire pour modifier le mot de passe. Voici le message :

Image non disponible

Quand le changement de mot de passe est réussi, un message en informe l'utilisateur. À la fermeture du message, le formulaire de changement de mot de passe est fermé et l'utilisateur se retrouve de nouveau sur l'application.

Image non disponible

Si l'utilisateur désire abandonner son changement de mot de passe, un clic sur le bouton Annuler ferme le formulaire et il se retrouve de nouveau sur l'application. La fermeture du formulaire par la croix X ramène aussi à l'application.

 
Sélectionnez
procedure TFormChgt.BtnAnnul2Click(Sender: TObject); //Abandon changement mot de passe
begin
  Close;
end;

Dans le cas où l'utilisateur souhaite à nouveau changer de mot de passe après avoir interrompu sa démarche précédente, la procédure d'effacement des champs de saisie est appelée à la réapparition du formulaire.

 
Sélectionnez
procedure TFormChgt.FormShow(Sender: TObject); //Effacement des champs du formulaire de Changement de mot de passe
begin
  Procrazchgt(Self);
end;

À la fermeture du formulaire, nous libérons la mémoire.

 
Sélectionnez
procedure TFormChgt.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  CloseAction:= caFree; //Libère la mémoire
end;

Nous avons vu précédemment que nous devons créer la fonction Testmdp. Nous nous rendons dans l'unité datamodule pour le faire.

 
Sélectionnez
function TData.Testmdp(cNmdp: String): boolean; //Fonction de test de mot de passe non identique à celui d'un autre compte de l'utilisateur
begin
  //Vérifie si le mot de passe n'est pas employé par l'utilisateur pour un de ses autres profils
  result:= False;
  SQLreqNMDP.Close;
  SQLreqNMDP.SQL.Text:='SELECT trigramme,paswd,groupe FROM t_user WHERE trigramme =:t AND paswd =:m;';
  SQLreqNMDP.ParamByName('t').asString:= User;
  SQLreqNMDP.ParamByName('m').asString:= cNmdp;
  SQLreqNMDP.Open;
    if SQLreqNMDP.FieldBYName('paswd').isNull then
  result:= True; //Mot de passe non identique à celui d'un autre compte de l'utilisateur
end;

La fonction de changement de mot de passe est aussi créée au sein de l'unité datamodule. Nous préférons ici une fonction qui assure le changement et retourne grâce au « bloc try » un résultat booléen permettant de le confirmer ou de gérer une éventuelle erreur pouvant se produire lors d'une utilisation « multiposte »644 commentaires Donner une note  l'article (4.5) L'utilisation d'une procédure aurait été adaptée seulement dans le cadre d'une utilisation « monoposte ».

 
Sélectionnez
function TData.Changement(cNmdp: String): boolean; //Fonction de changement de mot de passe
begin
  //Change le mot de passe en fonction du groupe d'appartenance de l'utilisateur
  result:= False;
  gpe:= SQLreqMDP.FieldBYName('groupe').asString; //Récupération du statut de l'utilisateur
  SQLreqNMDP.SQL.Text:='UPDATE t_user SET paswd =:p WHERE trigramme =:t AND groupe =:g;';
  SQLreqNMDP.ParamByName('t').asString:= User;
  SQLreqNMDP.ParamByName('p').asString:= cNmdp;
  SQLreqNMDP.ParamByName('g').asString:= gpe; //Discrimination par le statut de l'utilisateur
  try
  SQLreqNMDP.ExecSQL;
  result:= True;
  except
  result:= False;
  end;
end;

V-F. Le code du formulaire de gestion des utilisateurs

La fiche FormGutil constitue le formulaire qui permet à un administrateur de l'application d'inscrire ou de supprimer des utilisateurs. Ce formulaire est appelé depuis l'application. Il est seulement accessible aux administrateurs. Le code concernant ce formulaire est créé dans l'unité gutil.

Nous déclarons les variables et les fonctions de création et de suppression des utilisateurs dans lesquelles elles seront utilisées. Nous déclarons aussi la procédure Procrazgdu qui permettra d'effacer les champs du formulaire de gestion des utilisateurs après chaque création ou suppression d'un utilisateur.

 
Sélectionnez
  private
    util: String;
    nomu: String;
    prenu: String;
    mdpu: String;
    gpu: String;
    test: String;
    function Testsuppu(cutil,cgpu: String): boolean;
    function Testcreau(cutil,cnomu,cprenu,cgpu,cmdpu: String): boolean;
    procedure Procrazgdu(Form: TForm);

Nous déclarons l'unité datamodule dans les clauses uses au niveau de l'implémentation pour lier le formulaire de la gestion des utilisateurs à la base de données.

 
Sélectionnez
implementation

{$R *.lfm}

uses
  datamodule;

Nous élaborons la procédure Procrazgdu qui effacera les champs de saisie du formulaire suite à une création ou suppression d'utilisateur. Cette procédure permet ainsi de libérer les champs pour pouvoir faire plusieurs créations ou suppressions d'utilisateurs les unes après les autres sans avoir à effacer manuellement les champs. Les composants de type TEdit peuvent être effacés de « manière groupée » alors qu'une ligne de code est destinée au composant ComboGpe.

 
Sélectionnez
procedure TFormGutil.Procrazgdu(Form: TForm); //Procédure d'effacement du contenu des champs du formulaire
var
  I: Integer;
begin
  for I:= 0 to Form.ComponentCount - 1 do
    if Form.Components[I] is TEdit then
  TEdit(Form.Components[I]).Text:= '';
  ComboGpe.Text:= '';
end;

Si l'administrateur désire abandonner la création ou la suppression d'un utilisateur, un clic sur le bouton Annuler ferme le formulaire et il se retrouve de nouveau sur l'application. La fermeture du formulaire par la croix X ramène aussi à l'application.

 
Sélectionnez
procedure TFormGutil.Annul3Click(Sender: TObject); //Abandon gestion des utilisateurs
begin
  Close;
end;

À la fermeture du formulaire, la mémoire est libérée.

 
Sélectionnez
procedure TFormGutil.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  CloseAction:= caFree; //Libère la mémoire
end;

V-F-1. Création d'un utilisateur

Dans ce paragraphe, nous verrons qu'un utilisateur ne peut posséder qu'un profil ou compte par groupe et les mots de passe pour chacun devront être différents. Pour des raisons pratiques, les mots de passe saisis dans le formulaire n'ont pas à répondre aux règles que nous avons mises en place dans la conception du formulaire de changement de mot de passe. Ici, le but est de donner au nouvel utilisateur un mot de passe simple qu'il devra changer suite à sa première connexion. Par exemple : util01 pour un simple utilisateur ou admin01 pour un administrateur.

Pour créer un utilisateur, il faut s'assurer préalablement de la complétude des champs requis dans le formulaire de gestion des utilisateurs. Pour le faire, nous élaborons la fonction Testcreau.

 
Sélectionnez
function TFormGutil.Testcreau(cutil,cnomu,cprenu,cgpu,cmdpu: String): boolean;
var
  ListeDesCas: TStrings;
begin
  result:= False;
  ListeDesCas:= TstringList.create;
  try
    ListeDesCas.Add(cutil);
    ListeDesCas.Add(cnomu);
    ListeDesCas.Add(cprenu);
    ListeDesCas.Add(cgpu);
    ListeDesCas.Add(cmdpu);
  Case ListeDesCas.IndexOf(test) of
    0 : cutil:= '';
    1 : cnomu:= '';
    2 : cprenu:= '';
    3 : cgpu:= '';
    4 : cmdpu:= ''
  else
    result:= True;
  end;
  Case ListeDesCas.IndexOf(test) of
    0 : ShowMessage('Échec de création. Identifiant utilisateur non renseigné.');
    1 : ShowMessage('Échec de création. Nom utilisateur non renseigné.');
    2 : ShowMessage('Échec de création. Prénom utilisateur non renseigné.');
    3 : ShowMessage('Échec de création. Groupe utilisateur non renseigné.');
    4 : ShowMessage('Échec de création. Mot de passe utilisateur non renseigné.');
  end;
  finally ListeDesCas.Free;
  end;
end;

Le bouton Créer appelle la fonction Creatutil que nous créerons dans l'unité datamodule. Elle s'exécute après avoir répondu aux conditions de complétude des champs du formulaire. Parmi ces conditions, seront aussi sollicitées les fonctions Testgpu et Testmdpu que nous élaborerons également dans datamodule.

 
Sélectionnez
procedure TFormGutil.BtnCreaClick(Sender: TObject); //Appel création d'un utilisateur
var
  reply: integer;
  boxstyle: integer;
begin
  util:= EdIdentU.Text;
  nomu:= EdNomU.Text;
  prenu:= EdPrenU.Text;
  gpu:= ComboGpe.Text;
  mdpu:= EdMdpU.Text;
  //Teste la complétude des champs
    if Testcreau(util,nomu,prenu,gpu,mdpu)= False then
  exit;
  //Teste l'existence dans le groupe d'utilisateurs
    if Data.Testgpu(util,gpu)= True then
  ShowMessage('Échec de création. Utilisateur déjà existant dans ce groupe.')
    else
  //Teste si le mot de passe est identique à celui d'un autre compte de l'utilisateur
    if Data.Testmdpu(util,mdpu)= True then
  ShowMessage('Échec de création. Mot de passe identique à celui d''un autre compte de cet utilisateur.')
    else
  //Appel conditionnel de la fonction de création
    if Data.Creatutil(util,nomu,prenu,gpu,mdpu)= True then
  begin
    Procrazgdu(Self); //Efface les champs du formulaire
    with application do
    begin
      boxstyle:= MB_ICONQUESTION + MB_YESNO;
      reply:= MessageBox('Création réussie. Voulez-vous créer un autre utilisateur ?', 'Création utilisateur', boxstyle);
        if reply = IDYES then
      FormGutil.Show //Montre le formulaire de gestion des utilisateurs
        else
      FormGutil.Close; //Ferme le formulaire
    end;
  end;
end;

Lors de la création d'un utilisateur, chaque manquement dans les éléments à saisir renvoie un message d'information comme celui ci-après invitant l'administrateur à compléter le champ omis. À la fermeture du message l'administrateur revient sur le formulaire pour apporter les corrections ou abandonner la création. Exemple de message :

Image non disponible

En passant par la fonction Testgpu, la procédure interdit la création d'un deuxième compte utilisateur pour un utilisateur déjà présent dans le groupe sélectionné. Une tentative de création dans ces conditions ouvre un message qui une fois fermé remet l'administrateur sur le formulaire pour apporter les corrections ou abandonner la création.

Image non disponible

En passant par la fonction Testmdpu, la procédure interdit la création d'un compte utilisateur pour un utilisateur ayant le même mot de passe pour un autre de ses comptes. Ainsi, pour un même utilisateur ses comptes d'administrateur et de simple utilisateur ne peuvent être utilisés avec un même mot de passe. Une tentative de création dans ces conditions renvoie un message qui une fois fermé remet l'administrateur sur le formulaire pour apporter les corrections ou abandonner la création.

Image non disponible

Quand la création aboutit, un message informe l'administrateur et l'invite soit à revenir sur le formulaire en cliquant sur Yes pour créer un nouvel utilisateur, ou bien abandonner la création en cliquant sur No et revenir sur l'application.

Image non disponible

Nous avons vu précédemment que pour créer un utilisateur, il faut utiliser les fonctions Testgpu et Testmdpu ainsi que la procédure Creatutil. Pour concevoir celles-ci, nous nous rendons dans l'unité datamodule.

Commençons par la fonction Testgpu.

 
Sélectionnez
function TData.Testgpu(cutil,cgpu: String): boolean; //Fonction test de présence de l'utilisateur dans la table t_user selon son groupe d'appartenance
begin
  result:= False;
  SQLreqGutil.Close;
  SQLreqGutil.SQL.Text:='SELECT trigramme,groupe,paswd FROM t_user WHERE trigramme =:t AND groupe =:g;';
  SQLreqGutil.ParamByName('t').asString:= cutil;
  SQLreqGutil.ParamByName('g').asString:= cgpu;
  SQLreqGutil.Open;
    if SQLreqGutil.FieldBYName('groupe').asString <> '' then
  result:= True; //Utilisateur présent
end;

Ensuite, passons à la fonction Testmdpu.

 
Sélectionnez
function TData.Testmdpu(cutil,cmdpu: String): boolean; //Fonction test de présence de l'utilisateur dans la table t_user selon son mot de passe
begin
  result:= False;
  SQLreqGutil.Close;
  SQLreqGutil.SQL.Text:='SELECT trigramme,groupe,paswd FROM t_user WHERE trigramme =:t AND paswd =:m;';
  SQLreqGutil.ParamByName('t').asString:= cutil;
  SQLreqGutil.ParamByName('m').asString:= cmdpu;
  SQLreqGutil.Open;
    if SQLreqGutil.FieldBYName('paswd').asString <> '' then
  result:= True; //Utilisateur présent
end;

Enfin, pour terminer la partie création d'un utilisateur, nous créons la fonction Creatutil. La raison d'opter pour une fonction plutôt que pour une procédure est la même que celle pour le changement de mot de passe.

 
Sélectionnez
function TData.Creatutil(cutil,cnomu,cprenu,cgpu,cmdpu: String): boolean; //Fonction de création d'un utilisateur
begin
  result:= False;
  SQLreqGutil.SQL.Text:= 'INSERT INTO t_user (trigramme, nom, prenom, groupe, paswd) VALUES (:t, :n, :p, :g, :m);';
  SQLreqGutil.ParamByName('t').asString:= cutil;
  SQLreqGutil.ParamByName('n').asString:= cnomu;
  SQLreqGutil.ParamByName('p').asString:= cprenu;
  SQLreqGutil.ParamByName('g').asString:= cgpu;
  SQLreqGutil.ParamByName('m').asString:= cmdpu;
  try
  SQLreqGutil.ExecSQL;
  result:= True;
  except
  result:= False;
  end;
end;

V-F-2. Suppression d'un utilisateur

Nous revenons maintenant dans l'unité gutil pour réaliser la partie suppression d'un utilisateur.

Dans ce paragraphe, nous verrons que la suppression d'un utilisateur est sélective. Elle ne concerne que la suppression de l'utilisateur dans un groupe défini, préservant ainsi le compte ou profil que ce même utilisateur pourrait avoir dans un autre groupe.

Pour supprimer un utilisateur, il est nécessaire que les champs Identifiant util et Groupe util soient complétés. Pour le vérifier, nous créons la fonction Testsuppu.

 
Sélectionnez
function TFormGutil.Testsuppu(cutil,cgpu: String): boolean;
begin
  result:= False;
    if cutil = '' then
  ShowMessage ('Échec de suppression. Identifiant utilisateur non renseigné.')
    else
    if cgpu = '' then
  ShowMessage ('Échec de suppression. Groupe utilisateur non renseigné.')
    else
  result:= True;
end;

Le bouton Supprimer lance la fonction de suppression d'un utilisateur Suputil que nous élaborerons dans l'unité datamodule. Comme vu précédemment, seule la complétude des champs Identifiant util et Groupe util est requise pour procéder. La suppression sera alors soumise à la condition d'appartenance au groupe sélectionné dans ComboGpe et testée avec la fonction Testgpu déjà utilisée précédemment dans la partie création d'un utilisateur.

 
Sélectionnez
procedure TFormGutil.BtnSupClick(Sender: TObject); //Appel suppression d'un utilisateur
var
  reply: integer;
  boxstyle: integer;
begin
  util:= EdIdentU.Text;
  gpu:= ComboGpe.Text;
  //Teste la complétude des champs
    if Testsuppu(util,gpu)= False then
  exit;
  //Teste l'existence dans le groupe d'utilisateurs
    if Data.Testgpu(util,gpu)= False then
  ShowMessage('Échec de suppression. Utilisateur absent ou mal renseigné.')
    else
  //Appel conditionnel de la fonction de suppression
    if Data.Suputil(util,gpu)= True then
  begin
  Procrazgdu(Self); //Efface le contenu du formulaire
  with application do
    begin
      boxstyle:= MB_ICONQUESTION + MB_YESNO;
      reply:= MessageBox('Suppression réussie. Voulez-vous supprimer un autre utilisateur ?', 'Suppression utilisateur', boxstyle);
        if reply = IDYES then
      FormGutil.Show //Montre le formulaire de gestion des utilisateurs
        else
      FormGutil.Close; //Ferme le formulaire
    end;
  end;
end;

Lors de la suppression d'un utilisateur, chaque manquement dans les éléments à saisir renvoie un message d'information comme celui ci-après invitant l'administrateur à compléter le champ omis. À la fermeture du message, l'administrateur revient sur le formulaire pour corriger ou abandonner la suppression.

Image non disponible

En passant par la fonction Testgpu, la procédure permet d'autoriser ou non la suppression d'un utilisateur selon le groupe sélectionné. Une tentative de suppression dans le cas d'une inadéquation entre utilisateur et groupe ouvre un message qui à sa fermeture remet l'administrateur sur le formulaire pour apporter les corrections ou abandonner la suppression.

Image non disponible

Quand la suppression aboutit, un message informe l'administrateur et l'invite soit à revenir sur le formulaire en cliquant sur Yes pour supprimer un nouvel utilisateur, ou bien abandonner la suppression en cliquant sur No et revenir sur l'application.

Image non disponible

Pour finir, nous nous rendons maintenant dans l'unité datamodule où nous devons élaborer la fonction Suputil. Ici encore, la raison d'opter pour une fonction plutôt que pour une procédure est la même que celle pour le changement de mot de passe.

 
Sélectionnez
function TData.Suputil(cutil,cgpu: String): boolean; //Fonction de suppression d'un utilisateur
begin
  result:= False;
  SQLreqGutil.SQL.Text:= 'DELETE FROM t_user WHERE trigramme =:t AND groupe =:g;';
  SQLreqGutil.ParamByName('t').asString:= cutil;
  SQLreqGutil.ParamByName('g').asString:= cgpu;
  try
  SQLreqGutil.ExecSQL;
  result:= True;
  except
  result:= False;
  end;
end;

VI. Conclusion

Nous voilà parvenus au terme de ce tutoriel. Pour que tout fonctionne, il faut que la base de données soit démarrée. Il est aussi nécessaire qu'un premier administrateur ait été créé préalablement dans la table t_user en utilisant bien son identifiant de session comme identifiant de connexion à l'application. Celui-ci pourra ensuite créer les autres utilisateurs.

Nous avons vu comment profiter de la base de données pour mettre en place un formulaire de connexion avec identifiant et mot de passe. Nous y avons associé un formulaire de changement de mot de passe ainsi qu'un formulaire destiné aux administrateurs de l’application pour gérer les utilisateurs. Nous avons abordé la sécurisation des mots de passe lors de leur création. Cependant, la bonne pratique voudrait que les mots de passe ne soient pas lisibles en clair dans la table t_user. Pour faire cela, il faudrait les crypter ou les chiffrer, lors de leur inscription dans la table. Nous vous laissons le choix de la méthode…

Il est possible d'améliorer encore ce que nous avons élaboré ensemble. Maintenant, à vous d'être créatif pour mettre à votre goût et apporter les améliorations qui vous paraîtront nécessaires à ce que nous avons créé en cheminant dans ce tutoriel.

VII. Remerciements

Je remercie gvasseur58 pour ses encouragements pour me lancer et pour qui je me devais de finaliser ce tutoriel.

Je remercie SergioMaster, mon maître du code, qui m'a parfois poussé dans mes retranchements et dont la lecture technique m'a accompagné tout au long de ce laborieux cheminement. Il m'a donné beaucoup de son temps, de sa patience et de son savoir pour l'élaboration ce tutoriel.

Je remercie aussi ClaudeLELOUP. Sa grande qualité de relecture, nous permet de sortir la tête du code et d'écrire correctement ce vers quoi nous voulons amener nos lecteurs.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2021 Chrispi. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.