Une exigence courante lors de la création d'une application Web est d'implémenter un système de connexion, afin que les utilisateurs puissent s'authentifier avant d'accéder aux vues ou aux ressources protégées. Heureusement pour ceux qui créent des applications Node, il existe un middleware appelé Passport qui peut être déposé dans n'importe quelle application Web basée sur Express pour fournir des mécanismes d'authentification en seulement quelques commandes.
tutoriel, je vais vous montrer comment utiliser Passport pour implémenter l'authentification locale (c'est-à-dire la connexion avec un nom d'utilisateur et un mot de passe) avec un serveur principal MongoDB. Si vous cherchez à implémenter l'authentification via Facebook ou GitHub, veuillez vous référer à ce tutoriel .
Comme toujours, tout le code de cet article est disponible en téléchargement sur GitHub .
Prérequis
Pour suivre ce didacticiel, vous devez avoir installé Node et MongoDB sur votre machine.
Vous pouvez installer Node en vous dirigeant vers [1945901313]. ] la page de téléchargement officielle du nœud et en récupérant les binaires appropriés pour votre système. Alternativement, vous pouvez utiliser un gestionnaire de versions – un programme qui vous permet d'installer plusieurs versions de Node et de basculer entre elles à volonté. Si vous avez envie de suivre cette voie, veuillez consulter notre astuce, « Installer plusieurs versions de Node.js à l'aide de nvm ».
MongoDB est disponible en plusieurs éditions. Celui qui nous intéresse est l'édition communautaire de MongoDB.
La page d'accueil du projet contient une excellente documentation et je n'essaierai pas de la reproduire ici. Je vous propose plutôt des liens vers des instructions pour chacun des principaux systèmes d'exploitation:
Si vous utilisez une version de Linux non basée sur Ubuntu, vous pouvez consulter cette page pour obtenir des instructions d'installation pour autres distributions. MongoDB est également normalement disponible via les canaux logiciels officiels de Linux, mais parfois cela entraînera une version obsolète.
Remarque: Vous n'avez pas besoin d'entrer votre nom et votre adresse pour télécharger MongoDB. Si vous y êtes invité, vous pouvez normalement fermer la boîte de dialogue.
Si vous souhaitez un bref rappel sur l'utilisation de MongoDB, consultez notre guide du débutant, " Une introduction à MongoDB ".
Stratégies d'authentification: Session vs JWT
Avant de commencer, parlons brièvement des choix d'authentification.
De nombreux didacticiels en ligne aujourd'hui opteront pour l'authentification basée sur des jetons à l'aide de JSON Web Tokens (JWTs). Cette approche est probablement la plus simple et la plus populaire de nos jours. Il relègue une partie de la responsabilité d'authentification au client et lui fait signer un jeton qui est envoyé avec chaque demande, pour garder l'utilisateur authentifié.
L'authentification basée sur la session existe depuis plus longtemps. Cette méthode relègue le poids de l'authentification au serveur. Il utilise des cookies et voit l'application Node et la base de données fonctionner ensemble pour garder une trace de l'état d'authentification d'un utilisateur.
Dans ce tutoriel, nous allons utiliser l'authentification basée sur la session, qui est au cœur du passeport . stratégie locale
Les deux méthodes ont leurs avantages et leurs inconvénients. Si vous souhaitez en savoir plus sur la différence entre les deux, ce fil de débordement de pile peut être un bon point de départ.
Création du projet
Une fois que tous les logiciels prérequis sont définis , nous pouvons commencer.
Nous allons commencer par créer le dossier de notre application, puis accéder à ce dossier sur le terminal:
mkdir AuthApp
cd AuthApp
Pour créer l'application de nœud, nous utiliserons la commande suivante:
npm init
Vous serez invité à fournir des informations sur le package Node
du nœud. Continuez à appuyer sur Retournez pour accepter la configuration par défaut (ou utilisez l'indicateur
-y
).
Configuration d'Express
Maintenant, nous devons installer Express . Accédez au terminal et entrez cette commande:
npm install express
Nous devons également installer le middleware body-parser qui est utilisé pour analyser le corps de la requête que Passport utilise pour authentifier l'utilisateur. Et nous devons installer le middleware express-session .
Faisons-le. Exécutez la commande suivante:
npm install body-parser express-session
Une fois cela fait, créez un fichier index.js
dans le dossier racine de votre application et ajoutez-y le contenu suivant:
/ * EXPRESS SETUP * /
const express = require ('express');
const app = express ();
app.use (express.static (__ dirname));
const bodyParser = require ('body-parser');
const expressSession = require ('express-session') ({
secret: «secret»,
réenregistrer: faux,
saveUninitialized: false
});
app.use (bodyParser.json ());
app.use (bodyParser.urlencoded ({extended: true}));
app.use (expressSession);
const port = process.env.PORT || 3000;
app.listen (port, () => console.log ('App écoute sur port' + port));
Premièrement, nous avons besoin
Express et créons notre application Express en appelant express () . Ensuite, nous définissons le répertoire à partir duquel servir nos fichiers statiques.
La ligne suivante nous voit exiger
le middleware body-parser, qui nous aidera à analyser le corps de nos requêtes. Nous ajoutons également le middleware express-session pour nous aider à enregistrer le cookie de session.
Comme vous pouvez le voir, nous configurons express-session avec un secret
pour signer le cookie d'ID de session (vous devrait choisir une valeur unique ici), et deux autres champs, resave et saveUninitialized . Le champ resave
force la session à être sauvegardée dans le magasin de sessions, et le champ saveUninitialized
force à enregistrer une session qui n'est pas initialisée dans le magasin. Pour en savoir plus sur eux, consultez leur documentation, mais pour l'instant il suffit de savoir que pour notre cas nous voulons les garder faux
.
Ensuite, nous utilisons process.env.PORT
pour définir le port sur la variable de port d'environnement si elle existe. Sinon, nous utiliserons par défaut 3000
qui est le port que nous utiliserons localement. Cela vous donne suffisamment de flexibilité pour passer du développement directement à un environnement de production où le port peut être défini par un fournisseur de services comme, par exemple, Heroku . Juste en dessous, nous avons appelé app.listen () avec la variable de port que nous avons configurée et un simple journal pour nous faire savoir que tout fonctionne bien et sur quel port l'application écoute.
tout pour la configuration Express. Nous allons maintenant configurer Passport
.
Configurer Passport
Premièrement, nous installons Passport avec la commande suivante:
npm install passport
Ensuite, nous devons ajouter les lignes suivantes au bas du fichier index.js
:
/ * CONFIGURATION DU PASSEPORT * /
passeport const = exigé («passeport»);
app.use (passport.initialize ());
app.use (passport.session ());
Ici, nous avons besoin d'un passeport
et l'initialisons avec son middleware d'authentification de session, directement dans notre application Express.
Création d'un magasin de données MongoDB
Puisque nous supposons que vous avez déjà installé Mongo, vous devriez pouvoir démarrer le shell Mongo en utilisant la commande suivante:
mongo
Dans le shell, exécutez la commande suivante:
use MyDatabase;
Cela crée simplement un magasin de données nommé MyDatabase
.
Laissez le terminal là; nous y reviendrons plus tard.
Connexion de Mongo au nœud avec Mongoose
Maintenant que nous avons une base de données contenant des enregistrements, nous avons besoin d'un moyen de communiquer avec elle depuis notre application. Nous utiliserons Mongoose pour y parvenir. Pourquoi n'utilisons-nous pas simplement Mongo ordinaire? Eh bien, comme les développeurs de Mongoose aiment à le dire, A href = ”https://mongoosejs.com/docs/unstable/index.html”> sur leur site Web:
écrire la validation MongoDB, le casting et la plateforme de logique métier est un frein .
Mongoose va simplement nous faciliter la vie et rendre notre code plus élégant.
Allons de l'avant et installons-le avec la commande suivante:
npm install mongoose
Nous utiliserons également passport-local-mongoose ce qui simplifiera l'intégration entre Mongoose et Passport pour l'authentification locale. Il ajoutera un champ de hachage
et sel
à notre schéma afin de stocker le mot de passe haché et la valeur de sel. C'est formidable, car les mots de passe ne doivent jamais être stockés en texte brut dans une base de données .
Installons le package:
npm install passport-local-mongoose
Maintenant, nous devons configurer Mongoose. J'espère que vous connaissez maintenant l'exercice: ajoutez le code suivant au bas de votre fichier index.js
:
/ * MONGOOSE SETUP * /
const mangouste = require ('mangouste');
const passportLocalMongoose = require ('passport-local-mongoose');
mongoose.connect ('mongodb: // localhost / MyDatabase',
{useNewUrlParser: true, useUnifiedTopology: true});
const Schema = mangouste.Schema;
const UserDetail = nouveau schéma ({
nom d'utilisateur: String,
mot de passe: chaîne
});
UserDetail.plugin (passportLocalMongoose);
const UserDetails = mongoose.model ('userInfo', UserDetail, 'userInfo');
Ici, nous avons besoin des packages précédemment installés. Ensuite, nous nous connectons à notre base de données en utilisant mongoose.connect
et lui donnons le chemin vers notre base de données. Ensuite, nous utilisons un schéma pour définir notre structure de données. Dans ce cas, nous créons un schéma UserDetail
avec les champs username
et password
.
Enfin, nous ajoutons passportLocalMongoose
comme un plugin pour notre schéma. Cela fera partie de la magie dont nous avons parlé plus tôt. Ensuite, nous créons un modèle à partir de ce schéma. Le premier paramètre est le nom de la collection dans la base de données. Le deuxième est la référence à notre schéma, et le troisième est le nom que nous attribuons à la collection dans Mongoose.
C'est tout pour la configuration de Mongoose. Nous pouvons maintenant passer à la mise en œuvre de notre stratégie de passeport.
Implémentation de l'authentification locale
Et enfin, c'est ce que nous sommes venus faire ici! Configurons l'authentification locale. Comme vous le verrez ci-dessous, nous allons simplement écrire le code qui va le configurer pour nous:
/ * AUTHENTIFICATION LOCALE DU PASSEPORT * /
passport.use (UserDetails.createStrategy ());
passport.serializeUser (UserDetails.serializeUser ());
passport.deserializeUser (UserDetails.deserializeUser ());
Il y a pas mal de magie ici. Tout d'abord, nous faisons passeport
utiliser la stratégie locale en appelant createStrategy ()
sur notre modèle UserDetails
- avec l'aimable autorisation de passport-local-mongoose
- qui s'occupe de tout pour que nous n'ayons pas à mettre en place la stratégie.
Ensuite, nous utilisons les rappels serializeUser
et deserializeUser
. La première sera invoquée lors de l'authentification, et son travail consiste à sérialiser l'instance utilisateur avec les informations que nous lui transmettons et à la stocker dans la session via un cookie. Le second sera invoqué à chaque demande ultérieure de désérialisation de l'instance, en lui fournissant l'identifiant de cookie unique en tant que «justificatif d'identité». Vous pouvez en savoir plus à ce sujet dans la Documentation des passeports .
Itinéraires
Ajoutons maintenant quelques itinéraires pour tout lier ensemble. Tout d'abord, nous allons ajouter un package final. Accédez au terminal et exécutez la commande suivante:
npm install connect-sure-login
Le package connect-assure-login est un middleware qui garantit qu'un utilisateur est connecté. Si une demande reçue non authentifiée est reçue, la demande sera redirigée vers une page de connexion. Nous allons l'utiliser pour protéger nos itinéraires.
Maintenant, ajoutez ce qui suit au bas de index.js
:
/ * ROUTES * /
const connectEnsureLogin = require ('connect-sure-login');
app.post ('/ login', (req, res, next) => {
passport.authenticate («local»,
(err, utilisateur, info) => {
si (err) {
return next (err);
}
si (! utilisateur) {
return res.redirect ('/ login? info =' + info);
}
req.logIn (utilisateur, fonction (err) {
si (err) {
return next (err);
}
return res.redirect ('/');
});
}) (req, res, suivant);
});
app.get ('/ login',
(req, res) => res.sendFile ('html / login.html',
{root: __dirname})
);
app.get ('/',
connectEnsureLogin.ensureLoggedIn (),
(req, res) => res.sendFile ('html / index.html', {root: __dirname})
);
app.get ('/ private',
connectEnsureLogin.ensureLoggedIn (),
(req, res) => res.sendFile ('html / private.html', {root: __dirname})
);
app.get ('/ user',
connectEnsureLogin.ensureLoggedIn (),
(req, res) => res.send ({utilisateur: req.user})
);
En haut, nous avons besoin de connect-sure-login
. Nous y reviendrons plus tard.
Ensuite, nous avons configuré un itinéraire pour gérer une demande POST vers le chemin / login
. À l'intérieur du gestionnaire, nous utilisons la méthode passport.authenticate qui tente de s'authentifier avec la stratégie qu'il reçoit comme premier paramètre - dans ce cas local
. Si l'authentification échoue, il nous redirigera vers / login
mais il ajoutera un paramètre de requête - info
- qui contiendra un message d'erreur. Sinon, si l'authentification réussit, elle nous redirigera vers la route '/'
.
Ensuite, nous configurons la route / login
qui enverra la page de connexion. Pour cela, nous utilisons res.sendFile () et transmettons le chemin du fichier et notre répertoire racine, qui est celui sur lequel nous travaillons - d'où le __ dirname
. [19659003] La route / login
sera accessible à tous, mais pas la prochaine. Dans les itinéraires /
et / privés
nous enverrons leurs pages HTML respectives, et vous remarquerez quelque chose de différent ici. Avant le rappel, nous ajoutons l'appel connectEnsureLogin.ensureLoggedIn ()
. Voici notre garde-route. Son travail consiste à valider la session pour vous assurer que vous êtes autorisé à regarder cet itinéraire. Voyez-vous maintenant ce que je voulais dire plus tôt par «laisser le serveur faire le gros du travail»? Nous authentifions l'utilisateur à chaque fois.
Enfin, nous aurons besoin d'un itinéraire / utilisateur
qui renverra un objet avec nos informations utilisateur. C'est juste pour vous montrer comment vous pouvez obtenir des informations du serveur. Nous demanderons cette route au client et afficherons le résultat.
En parlant du client, faisons-le maintenant.
Le client
Le client devrait être assez simple. Nous allons créer des pages HTML
et un fichier CSS
. Commençons par la page d'accueil ou l'index. Dans la racine de votre projet, créez un dossier appelé html
et ajoutez un fichier appelé index.html
. Ajoutez-y ce qui suit:
Accueil
Nous avons ici une balise h1
vide où nous placerons notre message de bienvenue et, en dessous, un lien vers / private
. La partie cruciale ici est la balise de script
en bas où nous allons gérer l'obtention du nom d'utilisateur pour créer le message de bienvenue.
Ceci est divisé en quatre parties:
- Nous instancions l'objet de requête en utilisant
new XMLHttpRequest ()
.
- Nous avons défini la propriété
onreadystatechange
avec la fonction qui sera appelée après avoir obtenu notre réponse. Dans le rappel, nous vérifions si nous avons obtenu une réponse réussie et si oui, nous analysons la réponse, obtenons l'objet utilisateur (celui que nous avons envoyé dans la route / user
vous vous souvenez?), Et nous recherchez l'élément message de bienvenue
pour définir son innerText
sur notre user.username
.
- Nous
ouvrons ()
ouvrons () le ] GET
demande à l'utilisateur URL
et nous définissons le dernier paramètre sur true
pour le rendre asynchrone
.
- Enfin, nous
envoyer ()
la demande.
Nous allons maintenant créer la page de connexion. Comme précédemment, dans le dossier HTML, créez un fichier appelé login.html
et ajoutez-y le contenu suivant:
Login
Sur cette page, nous avons un formulaire de connexion simple, avec les champs nom d'utilisateur
et mot de passe
ainsi qu'un bouton Soumettre . En dessous, nous avons une étiquette où nous afficherons tous les messages d'erreur. Souvenez-vous, ceux-ci sont contenus dans la chaîne de requête.
La balise du script
en bas est beaucoup plus simple cette fois. Nous instancions un objet URLSearchParams
en passant la propriété window.location.search
qui contient la chaîne de paramètres dans notre URL. Ensuite, nous utilisons la méthode URLSearchParams.get ()
en transmettant le nom du paramètre que nous recherchons.
À ce stade, nous avons un message d'information ou non. Donc, si nous le faisons, nous obtenons l'élément message d'erreur
et définissons son innerText
sur quel que soit ce message, puis définissons sa propriété style.display
sur bloc
. Cela le rendra visible, étant donné que par défaut, il a un affichage : valeur "none"
.
Configurons maintenant la page privée. Encore une fois, créez un fichier dans le dossier HTML avec le nom private.html
et ajoutez le contenu suivant:
Private
Super simple. Juste un simple message et un lien Retour
qui nous ramène à la page d'accueil.
C'est tout pour le HTML, mais comme vous l'avez probablement remarqué, nous référençons un CSS
déposer les balises head
. Ajoutons ce fichier maintenant. Créez un dossier appelé css
à la racine de notre projet et ajoutez-y un fichier styles.css
avec le contenu suivant:
body {
affichage: flex;
align-items: centre;
fond: # 37474F;
famille de polices: monospace;
couleur: # cfd8dc;
justifier-contenu: centre;
taille de police: 20px;
}
.messagerie {
alignement du texte: centre;
}
une {
couleur: azur;
}
.champ {
marge: 10px;
}
contribution {
famille de polices: monospace;
taille de police: 20px;
frontière: aucune;
fond: # 1c232636;
couleur: # CFD8DC;
rembourrage: 7px;
bordure: # 4c5a61 solide 2px;
largeur: 300px;
}
.submit-btn {
largeur: 100%
}
.Titre {
marge: 10px 0px 20px 10px
}
#Message d'erreur {
couleur: # E91E63;
bloc de visualisation;
marge: 10px;
taille de police: grande;
max-width: fit-content;
}
Cela rendra nos pages suffisamment décentes. Voyons ça!
Prenez un terminal pointant vers la racine du projet et exécutez la commande suivante:
node index.js
Accédez maintenant à http: // localhost: 3000 / dans votre navigateur. Vous devez être redirigé vers la page de connexion. Si vous essayez d'accéder à http: // localhost: 3000 / private il devrait vous rediriger vers la page de connexion. Notre garde-route fait son travail.
Appuyez sur Ctrl + C dans la fenêtre du terminal pour arrêter notre serveur. Revenez ensuite au fichier index.js
et, au bas du fichier, ajoutez les lignes suivantes:
/ * ENREGISTREZ CERTAINS UTILISATEURS * /
UserDetails.register ({nom d'utilisateur: 'paul', actif: faux}, 'paul');
UserDetails.register ({nom d'utilisateur: 'jay', actif: faux}, 'jay');
UserDetails.register ({nom d'utilisateur: 'roy', actif: false}, 'roy');
Ceci utilise la méthode du registre passeport-local-mangouste
pour saler le mot de passe pour nous. Il nous suffit de le transmettre en texte brut.
Maintenant, nous exécutons node index.js
. Les utilisateurs seront créés. Vous devriez commenter ces dernières lignes maintenant.
Vous vous souvenez du terminal shell MongoDB que nous avons laissé ouvert? Retournez-y et tapez:
db.userInfo.find ()
Cela devrait montrer à vos trois utilisateurs et, comme vous pouvez le voir, le sel et le hachage occupent désormais une bonne partie de l'espace sur le terminal.
C'est tout ce dont nous avons besoin pour que l'application fonctionne. Nous avons terminé!
Retournez dans le navigateur, essayez de vous connecter avec l'une des informations d'identification que nous avons entrées et vous verrez le message de connexion avec le nom d'utilisateur donné.
Étapes suivantes
Nous ajouté les modules nécessaires pour que cette application fonctionne - rien de plus, rien de moins. Pour une application de production, vous devrez ajouter un autre middleware et séparer votre code en modules. Vous pouvez prendre cela comme un défi pour mettre en place un environnement propre et évolutif et le transformer en quelque chose d'utile!
La première et la plus simple chose que vous devriez essayer est d'ajouter la déconnexion
en utilisant la demande de passeport .logout () .
Vous pouvez ensuite essayer d'implémenter un flux de registres. Vous aurez besoin d'un formulaire d'inscription et d'un itinéraire pour parler. Vous devez utiliser le UserDetails.register ()
que nous avons ajouté plus tôt comme modèle. Pour une confirmation par e-mail, vous devriez consulter nodemailer .
Une autre chose que vous pourriez faire est d'essayer d'appliquer ces concepts à une application d'une seule page. Peut-être en utilisant Vue.js et son routeur. Et voilà votre week-end!
Conclusion
Eh bien, nous sommes enfin à la fin. Dans cet article, nous avons appris à implémenter l'authentification locale à l'aide de Passport
dans une application Node.js
. Au cours de ce processus, nous avons également appris à se connecter à MongoDB
à l'aide de Mongoose
.
Ce n'était peut-être pas aussi facile pour vous que j'ai essayé de le peindre, mais au moins vous j'ai vu que cela devient plus facile avec ces outils qui font de la magie en arrière-plan, nous laissant nous soucier seulement de ce que nous essayons de construire.
Les outils «magiques» ne sont pas toujours idéaux, mais des outils réputés et entretenus activement aident nous écrivons moins de code - et le code que vous n'écrivez pas est du code que vous ne maintenez pas, et le code que vous ne maintenez pas est du code que vous ne cassez pas.
Aussi, gardez à l'esprit que si un outil est activement maintenu par une équipe de base, les chances sont qu'ils savent ce qu'ils font mieux que nous. Délégué chaque fois que possible.
J'espère que vous avez apprécié ce didacticiel et que vous avez peut-être trouvé l'inspiration pour votre prochain projet.
Source link