Créer une API RESTful sécurisée avec CodeIgniter et des JWT
Temps de lecture: 10 minutes
L'utilisation et les applications croissantes des services cloud nécessitent un style architectural plus efficace que le protocole SOAP (Simple Object Access Protocol). REST (REpresentational State Transfer) permet une communication légère et sans état entre les clients et l'interface de programmation d'applications (API). La communication étant sans état, le contrôle d'accès des API RESTful est basé sur des tokens qui transportent suffisamment d'informations pour déterminer si le client est autorisé à effectuer l'action requêtée sur la ressource.
Dans ce tutoriel, je vais utiliser CodeIgniter pour créer une API RESTful. CodeIgniter est un puissant framework PHP avec un encombrement très faible qui permet aux développeurs de construire des applications Web complètes.
Conditions préalables
Une compréhension de base de CodeIgniter sera utile dans ce tutoriel. Cependant, je fournirai des explications et des liens vers la documentation officielle tout au long du tutoriel. En cas de doute concernant un concept, vous pouvez consulter le matériel lié avant de poursuivre.
De plus, les éléments suivants doivent être installés sur votre système :
- Composer. Composer sera utilisé pour la gestion des dépendances dans votre projet CodeIgniter.
- Une instance de base de données locale. Nous allons utiliser MySQL dans ce tutoriel, mais vous êtes libre de sélectionner votre service de base de données préféré
- Postman ou une application similaire pour tester nos points de terminaison. Vous pouvez également utiliser cURL à cet effet.
Ce que nous allons construire
Pour démontrer comment créer une API CodeIgniter sécurisée, nous allons créer une API qui sera utilisée pour gérer la base de données client d'une entreprise. Cette base de données contient les données suivantes sur chaque client :
- Nom
- Adresse e-mail
- Montant payé pour retenir les services de l'entreprise (acompte)
L'API obtenue à la fin de ce tutoriel présentera les fonctionnalités suivantes :
- Enregistrer un nouvel utilisateur
- Authentifier un utilisateur existant
- Ajouter un nouveau client
- Modifier les détails d'un client existant
- Afficher tous les clients
- Afficher un seul client par ID
- Supprimer un seul client par ID
Les fonctions 3 à 7 seront limitées aux utilisateurs authentifiés.
Mise en route
Créez un nouveau projet CodeIgniter à l'aide de Composer.
Ceci créera un nouveau projet CodeIgniter dans un dossier nommé ci-secure-api. Une fois l'installation terminée, accédez au dossier de projet nouvellement créé à partir du terminal et exécutez l'application sur le serveur de développement local fourni avec CodeIgniter. Pour ce faire, utilisez la commande suivante :
Accédez à http://localhost:8080/ depuis votre navigateur pour afficher la page d'accueil.
Préparation des variables d'environnement
Maintenant que CodeIgniter est installé et en cours d'exécution, l'étape suivante consiste à fournir des variables d'environnement qui seront utilisées par notre application. Arrêtez l'exécution de l'application en appuyant sur les touches CTRL + C
du clavier et effectuez une copie du fichier .env nommé .env à l'aide de la commande ci-dessous :
CodeIgniter démarre en mode production par défaut. Dans le cadre de ce tutoriel, nous allons le passer en mode développement. Pour ce faire, annuler le commentaire de la ligne ci-dessous et définissez-la sur development :
Ensuite, créez une base de données dans votre environnement local et supprimez le commentaire des variables suivantes pour mettre à jour chaque valeur et établir une connexion réussie à la base de données :
Remplacez les espaces réservés YOUR_DATABASE
, YOUR_DATABASE_USERNAME
et YOUR_DATABASE_PASSWORD
par vos propres valeurs.
Migrations et seeders
Maintenant que nous avons créé une base de données et configuré une connexion à celle-ci, nous allons créer des migrations pour les tables user
et client
. Les fichiers de migration sont généralement utiles pour créer une structure de base de données appropriée. Les migrations et les seeders seront créés à l'aide de l'outil CLI CodeIgniter.
Exécutez la commande suivante dans le terminal :
L'interface de ligne de commande vous demandera de nommer le fichier de migration, après quoi le fichier de migration sera créé dans le répertoire App/Database/Migrations. Pour ce tutoriel, vous allez créer deux fichiers de migration nommés :
add_client
add_user
Le nom du fichier de migration sera précédé d'une séquence numérique au format de date AAAA-MM-JJ-HHIISS
. Reportez-vous à la documentation CodeIgniter pour obtenir une explication plus détaillée.
Ensuite, mettez à jour le contenu du fichier de migration add_client
comme suit :
Ici, nous avons spécifié les champs et les types de données correspondants pour la table Client.
Ouvrez ensuite le fichier de migration add_user
et remplacez son contenu par ce qui suit :
Le contenu ci-dessus vous aidera à créer la table user et ses champs. Exécutez maintenant vos migrations à l'aide de la commande ci-dessous :
Pour faciliter le développement, seedez des données client factices dans votre base de données. L'ensemble factice fzaninotto est une dépendance par défaut dans le squelette CodeIgniter et peut être utilisé pour ajouter des clients aléatoires à la base de données. Tout comme pour la migration, l'outil CLI CodeIgniter sera utilisé pour créer un seeder pour les clients. Exécutez la commande suivante :
L'outil CLI requêtera le nom ClientSeeder
. Un fichier ClientSeeder.php sera créé dans le répertoire App/Database/Seeds. Ouvrez le fichier et remplacez son contenu par ce qui suit :
Peuplez la base de données avec des clients factices à l'aide de la commande suivante :
À ce stade, la base de données doit avoir une structure similaire à la capture d'écran ci-dessous :
Modèles d'entité
Pour l'interaction de l'API avec la base de données, le modèle de CodeIgniter sera utilisé. Pour que cela fonctionne, deux modèles seront créés : un pour l'utilisateur et un autre pour le client.
Ouvrez le répertoire App/Models et créez les fichiers suivants :
- UserModel.php
- ClientModel.php
Dans UserModel.php, ajoutez ce qui suit :
Les fonctions beforeInsert
et beforeUpdate
vous permettent d'effectuer une opération sur l'entité User avant de l'enregistrer dans la base de données. Dans ce cas, le mot de passe de l'utilisateur est hashé avant d'être enregistré dans la base de données.
Ajoutez le code suivant au fichier ClientModel.php :
Le champ $table
permet au modèle de savoir avec quelle table de base de données il fonctionne principalement. $allowedFields
permet au modèle de savoir quelles colonnes de la table peuvent être mises à jour. La fonction findClientById
fournit une abstraction propre pour extraire un client de la base de données en fonction de l'id
fourni.
Une fois les modèles et la base de données implémentés, les utilisateurs peuvent être ajoutés et authentifiés. Les utilisateurs autorisés peuvent également interagir avec la clientèle actuelle.
Implémentation de JWT
Les Web JSON Web Tokens seront utilisés pour authentifier les utilisateurs et empêcher les utilisateurs non autorisés d'afficher la liste des clients. Pour que cela fonctionne, l'API fournit un token lorsque l'utilisateur s'inscrit ou se connecte correctement. Ce token sera ajouté à l'en-tête des requêtes suivantes pour s'assurer que l'API peut identifier l'utilisateur à l'origine de la requête. Dans ce tutoriel, l'ensemble firebase/php-jwt sera utilisé pour générer les tokens. Exécutez ce qui suit pour l'installer à l'aide de Composer :
Une fois l'installation terminée, ajoutez les éléments suivants à votre fichier .env :
Ensuite, créez une fonction d'aide pour obtenir la clé secrète dans la classe Services. Accédez à App/Config/Services.php et ajoutez ce qui suit :
Création d'un JWT Helper
Pour faciliter la génération et la vérification des tokens, un fichier Helper sera créé. Cela nous permet de séparer les préoccupations dans notre application. Dans le répertoire App/Helpers, créez un fichier nommé jwt_helper.php. Votre fichier devrait ressembler à ceci :
La fonction getJWTFromRequest
vérifie l'en-tête Authorization de la requête entrante et renvoie la valeur du token. Si l'en-tête est manquant, une exception est déclenchée. Celle-ci entraîne à son tour le renvoi d'une réponse HTTP_UNAUTHORIZED
(401).
La fonction validateJWTFromRequest
utilise le token obtenu au moyen de la fonction getJWTFromRequest
. Elle décode ce token afin d'obtenir l'e-mail pour lequel la clé a été générée. Elle tente ensuite de trouver un utilisateur avec cette adresse e-mail dans la base de données. Si l'utilisateur n'a pas été trouvé, le modèle d'utilisateur déclenche une exception qui est détectée et renvoyée à l'utilisateur sous la forme d'une réponse HTTP_UNAUTHORIZED
(401).
La fonction getSignedJWTForUser
est utilisée pour générer un token pour un utilisateur authentifié. Le JWT codé contient les détails suivants :
- Adresse e-mail de l'utilisateur authentifié. Elle est utilisée dans les requêtes ultérieures pour valider la source de la requête.
- Heure à laquelle le token a été généré (
iat
). - Heure d'expiration du token (exp). Elle est obtenue en ajoutant la valeur
JWT_TIME_TO_LIVE
de notre fichier .env à l'heure actuelle.
Création d'un filtre d'authentification
Dans le répertoire App/Filters, créez un fichier nommé JWTAuthenticationFilter.php. Ce filtre permet de vérifier l'API du JWT avant de transmettre la requête au contrôleur. Si aucun JWT n'est fourni ou si le JWT fourni a expiré, une réponse HTTP_UNAUTHORIZED
(401) est renvoyée avec un message d'erreur approprié. Ajoutez ce qui suit à votre fichier :
Comme vous pouvez le voir, JWT Helper est chargé en premier, puis les fonctions getJWTFromRequest
et validateJWTFromRequest sont utilisées pour s'assurer que la requête provient d'un utilisateur authentifié avec un token valide.
Enregistrez votre filtre JWTAuthentication et spécifiez le chemin à protéger. Cette opération s'effectue dans le fichier App/Config/Filters.php. Mettez à jour les tableaux $aliases
et $filters
comme suit :
REMARQUE : la barre d'outils de débogage est préchargée par défaut. Il existe des conflits connus, car la barre d'outils de débogage est toujours en construction. Pour la désactiver, ajoutez un commentaire sur l'élément 'toolbar'
dans le tableau $globals
.
En ajoutant ces éléments, la fonction before
dans JWTAuthenticationFilter.php est appelée chaque fois qu'une requête est envoyée à un endpoint commençant par le client. Cela signifie que le contrôleur reçoit/traite la requête uniquement si son en-tête contient un token valide.
Même si nous n'avons pas de contrôleur, nous pouvons vérifier que notre application fonctionne jusqu'à présent. Ouvrez Postman et faites une requête GET à http://localhost:8080/client. Vous devriez voir quelque chose de similaire à la capture d'écran ci-dessous :
Ouvrez ensuite le fichier App/Controllers/BaseController.php et ajoutez la fonction suivante :
Cette fonction sera utilisée par vos contrôleurs pour renvoyer les réponses JSON au client.
REMARQUE : n'oubliez pas d'importer ResponseInterface.
BaseController
étend le Controller
de CodeIgniter, qui fournit des assistants et d'autres fonctions facilitant le traitement des requêtes entrantes. L'une de ces fonctions est validate
qui utilise le service de validation de CodeIgniter pour vérifier une requête par rapport aux règles (et aux messages d'erreur si nécessaire) spécifiées dans les fonctions de notre contrôleur. Cette fonction donne de bons résultats avec les requêtes de formulaire (form-data avec Postman). Cependant, elle ne serait pas en mesure de valider les requêtes JSON brutes envoyées à notre API. En effet, le contenu de la requête JSON est stocké dans le champ body
tandis que le contenu de la requête form-data est stocké dans le champ post
.
Pour contourner ce problème, nous allons écrire une fonction qui vérifie les deux champs dans une requête afin d'obtenir son contenu. Ajoutez ce qui suit à App/Controllers/BaseController.php :
REMARQUE : n'oubliez pas d'importer la classe IncomingRequest.
Ensuite, déclarez une fonction qui exécute le service de validation par rapport à $input
de notre fonction précédente. Cette fonction est presque la même que la fonction validate
intégrée, sauf qu'au lieu d'exécuter la vérification sur IncomingRequest
, nous l'exécutons sur l'entrée que nous avons capturée à partir de la fonction getRequestInput
.
REMARQUE : n'oubliez pas d'importer les classes nécessaires.
Une fois cela mis en place, ajoutons la logique pour enregistrer et authentifier les utilisateurs.
Contrôleur d'authentification
Ensuite, créez un fichier nommé Auth.php dans le répertoire App/Controllers. Mettez à jour le fichier comme indiqué ci-dessous :
Enregistrement
Pour enregistrer un nouvel utilisateur avec succès, les champs suivants sont obligatoires :
- Un nom.
- Une adresse e-mail dans un format valide ne comportant pas moins de 8 caractères et pas plus de 255 caractères.
- Un mot de passe de 8 caractères minimum et de 255 caractères maximum.
La requête entrante est vérifiée par rapport aux règles spécifiées. Les requêtes non valides sont ignorées avec un code (400) HTTP_BAD_REQUEST
et un message d'erreur. Si la requête est valide, les données utilisateur sont enregistrées et un token est renvoyé avec les détails enregistrés de l'utilisateur (à l'exception du mot de passe). La réponse HTTP_CREATED
(201) informe le client qu'une nouvelle ressource a été créée.
En effectuant une requête POST sur le endpoint du registre (http://localhost:8080/auth/register) avec un nom (name
), une adresse e-mail (e-mail
) et un mot de passe (password) valides, vous obtenez une réponse similaire à celle présentée ci-dessous :
Authentification
Une authentification réussie nécessite les éléments suivants :
- Une adresse e-mail dans un format valide ne comportant pas moins de 8 caractères et pas plus de 255 caractères. En outre, l'adresse e-mail doit correspondre à celle d'un utilisateur enregistré.
- Un mot de passe de 8 caractères minimum et de 255 caractères maximum. Comme pour l'adresse e-mail, le hachage du mot de passe fourni doit correspondre au hachage du mot de passe stocké associé à l'adresse e-mail fournie.
Cependant, faire de même pour le endpoint de connexion (http://localhost:8080/auth/login) entraînerait une erreur de serveur interne (code HTTP 500). La raison est que nous utilisons une fonction validateUser
dans nos règles de validation que nous n'avons pas encore créées.
Validation de l'utilisateur
Créez un nouveau répertoire appelé Validation dans le répertoire app. Dans le dossier app/Validation, créez un fichier nommé UserRules.php et ajoutez le code suivant au fichier :
Ouvrez ensuite le fichier App/Config/Validation.php et modifiez le tableau $ruleSets
pour inclure vos UserRules. $ruleSets
doit ressembler à ceci :
Avec les règles de validation personnalisées mises en place, la requête d'authentification fonctionne comme prévu. Testez ceci en envoyant une requête POST HTTP au endpoint http://localhost:8080/auth/login avec les détails de l'utilisateur créé précédemment :
Création d'un contrôleur client
Pour le contrôleur client, nous allons spécifier les chemins dans le fichier app/Config/Routes.php. Ouvrez le fichier et ajoutez-y les chemins suivants :
En procédant ainsi, votre API est capable de traiter les requêtes avec le même endpoint, mais des verbes HTTP différents.
Ensuite, dans le répertoire App/Controllers, créez un fichier appelé Client.php. Le contenu du fichier doit être le suivant :
Les fonctions index
, store
et show
sont utilisées pour traiter les requêtes d'affichage de tous les clients, d'ajout d'un nouveau client et d'affichage d'un seul client respectivement.
Ensuite, créez deux fonctions update
et destroy
. La fonction update
sera utilisée pour traiter les requêtes de modification d'un client. Aucun des champs n'est requis, donc toute valeur attendue qui n'est pas fournie dans la requête est supprimée avant la mise à jour du client dans la base de données. La fonction destroy
traite les requêtes de suppression d'un client particulier.
Maintenant que ces éléments sont en place, notre API est prête à être consommée. Redémarrez votre application et testez-la en envoyant des requêtes (via Postman, cURL ou votre application préférée).
Ajout d'un token d'accès
Une fois le processus d'enregistrement et de connexion terminé, copiez la valeur de access_token
de la réponse. Ensuite, cliquez sur l'onglet Authorization
, sélectionnez Bearer token
dans la liste déroulante et collez la valeur de access_token
copiée précédemment :
Création d'un nouveau client
Pour créer un nouveau client, envoyez une requête HTTP POST
à http://localhost:8080/client :
Récupération de la liste de tous les clients
Pour récupérer la liste des clients créés jusqu'à présent, envoyez une requête HTTP GET
à http://localhost:8080/client :
Récupération des détails d'un client par ID
Récupérez les détails d'un client particulier en envoyant une requête HTTP GET
à http://localhost:8080/client/1. Dans ce cas, 1 a été utilisé pour spécifier l'id unique du client qui doit être extrait de la base de données :
Conclusion
Dans cet article, nous avons créé une API PHP à l'aide de CodeIgniter. Cela a permis l'exécution d'opérations CRUD (Create [Créer], Read [Lire], Update [Mettre à jour], Delete [Supprimer]) de base sur une ressource (client). En outre, nous avons ajouté une couche de sécurité en limitant l'accès à la ressource. Nous avons également appris à structurer notre projet de manière à séparer les concerns et à rendre notre application plus faiblement couplée.
L'intégralité du code de ce tutoriel est disponible sur GitHub. N'hésitez pas à approfondir votre exploration. J'ai hâte de voir ce que vous allez construire !
Oluyemi est un passionné de technologie, spécialisé dans le domaine de l'ingénierie des télécommunications. Son intérêt marqué pour la résolution des problèmes quotidiens rencontrés par les utilisateurs l'ont incité à se lancer dans la programmation. Depuis, il met ses compétences en matière de résolution de problèmes au service de la création de logiciels pour le Web et les appareils mobiles. Ingénieur logiciel full stack et fervent défenseur du partage des connaissances, Oluyemi a publié de nombreux contenus et articles techniques sur plusieurs blogs sur Internet. Féru de technologie, il consacre une partie de son temps libre à tester de nouveaux frameworks et langages de programmation.
- Twitter : https://twitter.com/yemiwebby
- GitHub : https://github.com/yemiwebby
- Site Web : https://yemiwebby.com.ng/
Articles associés
Ressources connexes
Twilio Docs
Des API aux SDK en passant par les exemples d'applications
Documentation de référence sur l'API, SDK, bibliothèques d'assistance, démarrages rapides et didacticiels pour votre langage et votre plateforme.
Centre de ressources
Les derniers ebooks, rapports de l'industrie et webinaires
Apprenez des experts en engagement client pour améliorer votre propre communication.
Ahoy
Le hub de la communauté des développeurs de Twilio
Meilleures pratiques, exemples de code et inspiration pour créer des expériences de communication et d'engagement numérique.