L'authentification est l'une des tâches les plus difficiles pour les développeurs nouveaux dans GraphQL. Il existe de nombreuses considérations techniques impliquées, notamment en choisissant un ORM facile à définir, comment générer un jeton sécurisé et un mot de passe de hachage, et même quelle bibliothèque HTTP à utiliser et comment l'utiliser.
Cet article se concentre sur l'authentification locale . C'est probablement le moyen le plus populaire pour les sites Web modernes de gérer l'authentification, qui est réalisée en demandant les e-mails et les mots de passe des utilisateurs (par opposition à l'utilisation de l'authentification Google).
En outre, cet article utilise Apollo Server 2, JSON Web Tokens (JWT) et séquestre ORM pour créer une API d'authentification Node.js.
Traitement d'authentification
Connectez-vous au système:
- L'authentification identifie ou authentifie les utilisateurs.
- Autorise la vérification des itinéraires (ou des parties de l'application) auxquels un utilisateur authentifié peut accéder.
Les étapes pour implémenter ce processus sont les suivantes:
- Les utilisateurs s'inscrivent avec le mot de passe et l'e-mail.
- Les informations d'identification de l'utilisateur sont stockées dans la base de données.
- Une fois l'inscription terminée, l'utilisateur sera redirigé vers la page de connexion.
- Après l'authentification, l'utilisateur aura accès à une ressource spécifique.
- Le statut de l'utilisateur est stocké dans n'importe quel support de stockage de navigateur (par exemple, localstorage, cookies, sessions) ou dans un JWT.
Condition préalable
Avant d'aller plus loin, voici quelques étapes que vous devez suivre.
- Node.js 6 ou plus
- Fil (recommandé) ou NPM
- Terrain de jeu GraphQL
- Bases de GraphQL et Node.js
- … Un cœur qui cherche des connaissances!
Dépendances
Voici une longue liste, commençons:
- APOLLO Server : un serveur GraphQL open source compatible avec tout type de client GraphQL. Dans ce projet, nous n'utiliserons pas Express comme serveur. Au lieu de cela, nous profiterons des capacités d'Apollo Server pour exposer notre API GraphQL.
- BCRYPTJS : Nous voulons hacher le mot de passe utilisateur dans notre base de données. C'est pourquoi nous allons utiliser Bcrypt. Il s'appuie sur l'interface GetRandomValues de l'API Web Crypto pour obtenir des nombres aléatoires sécurisés.
- Dotenv : nous utiliserons DOTENV pour charger des variables d'environnement de notre fichier .env.
- JSONWEBToken : Une fois que l'utilisateur s'est connecté, chaque demande suivante contiendra un JWT, permettant à l'utilisateur d'accéder aux itinéraires, aux services et aux ressources autorisées en utilisant le jeton. JSONWEBToken sera utilisé pour générer des JWT, qui sont utilisés pour vérifier l'identité de l'utilisateur.
- NODEMON : Un outil qui aide à développer des applications basées sur des nœuds en redémarrant automatiquement les applications de nœuds lorsqu'un changement de répertoire est détecté. Nous ne voulons pas que le serveur soit fermé et démarré chaque fois que le code change. Nodemon vérifie les modifications de notre application à chaque fois et redémarre automatiquement le serveur.
- MySQL2 : Client SQL de Node.js. Nous en avons besoin pour nous connecter à notre serveur SQL afin que nous puissions exécuter la migration.
- SECELILISE : SECELILSE est un nœud ORM basé sur des promesses utilisé dans Postgres, MySQL, MARIADB, SQLITE et Microsoft SQL Server. Nous utiliserons Sequelize pour générer automatiquement nos migrations et nos modèles.
- CLI séquestre : nous utiliserons le CLI Sequelize pour exécuter la commande Sequelize. Installez-le globalement dans le terminal à l'aide du fil Add - Global Sequelize-CLI.
Configuration de la structure du répertoire et de l'environnement de développement
Créons un tout nouveau projet. Créez un nouveau dossier et créez ce qui suit:
<code>yarn init -y</code>
L'indicateur -y signifie que nous sélectionnons oui pour tous les problèmes d'initiation du fil et utilisons la valeur par défaut.
Nous devons également placer un fichier package.json dans le dossier, alors installons les dépendances du projet:
<code>yarn add apollo-server bcryptjs dotenv jsonwebtoken nodemon sequelize sqlite3</code>
Ensuite, ajoutons Babel à notre environnement de développement:
<code>yarn add babel-cli babel-preset-env babel-preset-stage-0 --dev</code>
Maintenant, configurons Babel. Exécutez Touch .Babelrc dans le terminal. Cela créera et ouvrira un fichier de configuration Babel où nous ajouterons ce qui suit:
<code>{ "presets": ["env", "stage-0"] }</code>
Il serait encore mieux que nos serveurs commençaient et migraient des données. Nous pouvons le faire automatiquement en mettant à jour Package.json avec les suivants:
<code>"scripts": { "migrate": " sequelize db:migrate", "dev": "nodemon src/server --exec babel-node -e js", "start": "node src/server", "test": "echo \"Error: no test specified\" && exit 1" },</code>
Voici notre fichier complet de package.json complet:
<code>{ "name": "graphql-auth", "version": "1.0.0", "main": "index.js", "scripts": { "migrate": " sequelize db:migrate", "dev": "nodemon src/server --exec babel-node -e js", "start": "node src/server", "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "apollo-server": "^2.17.0", "bcryptjs": "^2.4.3", "dotenv": "^8.2.0", "jsonwebtoken": "^8.5.1", "nodemon": "^2.0.4", "sequelize": "^6.3.5", "sqlite3": "^5.0.0" }, "devDependencies": { "babel-cli": "^6.26.0", "babel-preset-env": "^1.7.0", "babel-preset-stage-0": "^6.24.1" } }</code>
Maintenant que notre environnement de développement est configuré, passons à la base de données, nous y stockons des choses.
Paramètres de la base de données
Nous utiliserons MySQL comme base de données et utiliserons ORM séquestre pour la cartographie relationnelle. Exécutez Sequelize init (en supposant que vous l'avez installé à l'échelle mondiale auparavant). Cette commande doit créer trois dossiers: / config / modèles et / migrations. À l'heure actuelle, notre structure de répertoire de projet se forme.
Configurons notre base de données. Tout d'abord, créez un fichier .env dans le répertoire racine du projet et collez ce qui suit:
<code>NODE_ENV=development DB_HOST=localhost DB_USERNAME= DB_PASSWORD= DB_NAME=</code>
Ensuite, accédez au dossier / config que nous venons de créer et de renommer le fichier config.json dans config.js. Ensuite, mettez le code suivant:
<code>require('dotenv').config() const dbDetails = { username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, host: process.env.DB_HOST, dialect: 'mysql' } module.exports = { development: dbDetails, production: dbDetails }</code>
Ici, nous lisons les détails de la base de données que nous définissons dans le fichier .env. process.env est une variable globale injectée par Node pour représenter l'état actuel de l'environnement système.
Mettons à jour nos détails de base de données avec les données appropriées. Ouvrez la base de données SQL et créez un tableau nommé GraphQL_Auth. J'utilise Laragon comme serveur local et j'utilise PhpMyAdmin pour gérer les tables de base de données.
Peu importe ce que vous utilisez, nous devons mettre à jour le fichier .env avec les dernières informations:
<code>NODE_ENV=development DB_HOST=localhost DB_USERNAME=graphql_auth DB_PASSWORD= DB_NAME=</code>
Configurons la séquelle. Créez un fichier .SeveLizerc dans le répertoire racine du projet et collez ce qui suit:
<code>const path = require('path') module.exports = { config: path.resolve('config', 'config.js') }</code>
Intégrons maintenant notre configuration dans le modèle. Allez dans le dossier index.js dans / modèles et modifiez la variable de configuration.
<code>const config = require(__dirname '/../../config/config.js')[env]</code>
Enfin, écrivons notre modèle. Pour ce projet, nous avons besoin d'un modèle d'utilisateur. Utilisons la séquelle pour générer automatiquement le modèle. Voici ce que nous devons exécuter dans le terminal pour le configurer:
<code>sequelize model:generate --name User --attributes username:string,email:string,password:string</code>
Montons le modèle qu'il crée pour nous. Allez dans le dossier user.js dans / modèles et collez ce qui suit:
<code>'use strict'; module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', { username: { type: DataTypes.STRING, }, email: { type: DataTypes.STRING, }, password: { type: DataTypes.STRING, } }, {}); return User; };</code>
Ici, nous créons des propriétés et des champs pour les noms d'utilisateur, les e-mails et les mots de passe. Exécutons la migration pour suivre les changements dans notre schéma:
<code>yarn migrate</code>
Maintenant, écrivons le modèle et l'analyseur.
Intégrer le schéma et l'analyseur avec GraphQL Server
Dans cette section, nous définirons nos modèles, rédigerons les fonctions d'analyse et les exposerons à notre serveur.
modèle
Dans le dossier SRC, créez un nouveau dossier nommé / schéma et créez un fichier nommé schema.js. Collez le code suivant:
<code>const { gql } = require('apollo-server') const typeDefs = gql` type User { id: Int! username: String email: String! } type AuthPayload { token: String! user: User! } type Query { user(id: Int!): User allUsers: [User!]! me: User } type Mutation { registerUser(username: String, email: String!, password: String!): AuthPayload! login (email: String!, password: String!): AuthPayload! } ` module.exports = typeDefs</code>
Ici, nous importons GraphQL-Tag depuis Apollo-Server. Apollo Server doit envelopper notre modèle avec GQL.
Analyseur
Dans le dossier SRC, créez un nouveau dossier nommé / résolveurs et créez un fichier nommé résolver.js. Collez le code suivant:
<code>const bcrypt = require('bcryptjs') const jsonwebtoken = require('jsonwebtoken') const models = require('../models') require('dotenv').config() const resolvers = { Query: { async me(_, args, { user }) { if(!user) throw new Error('You are not authenticated') return await models.User.findByPk(user.id) }, async user(root, { id }, { user }) { try { if(!user) throw new Error('You are not authenticated!') return models.User.findByPk(id) } catch (error) { throw new Error(error.message) } }, async allUsers(root, args, { user }) { try { if (!user) throw new Error('You are not authenticated!') return models.User.findAll() } catch (error) { throw new Error(error.message) } } }, Mutation: { async registerUser(root, { username, email, password }) { try { const user = await models.User.create({ username, email, password: await bcrypt.hash(password, 10) }) const token = jsonwebtoken.sign( { id: user.id, email: user.email}, process.env.JWT_SECRET, { expiresIn: '1y' } ) return { token, id: user.id, username: user.username, email: user.email, message: "Authentication succesfull" } } catch (error) { throw new Error(error.message) } }, async login(_, { email, password }) { try { const user = await models.User.findOne({ where: { email }}) if (!user) { throw new Error('No user with that email') } const isValid = await bcrypt.compare(password, user.password) if (!isValid) { throw new Error('Incorrect password') } // return jwt const token = jsonwebtoken.sign( { id: user.id, email: user.email}, process.env.JWT_SECRET, { expiresIn: '1d'} ) return { token, user } } catch (error) { throw new Error(error.message) } } }, } module.exports = resolvers</code>
Il y a beaucoup de code, voyons ce qui se passe là-bas.
Tout d'abord, nous importons notre modèle, BCrypt et JSONWebtoken, puis initialisons nos variables d'environnement.
Ensuite, la fonction d'analyseur. Dans l'analyseur de requête, nous avons trois fonctions (moi, utilisateur et allusers):
- Me requête pour obtenir des informations détaillées de l'utilisateur actuellement connecté. Il accepte les objets utilisateur comme paramètres de contexte. Le contexte est utilisé pour donner accès à notre base de données, qui est utilisée pour charger les données de l'utilisateur via l'ID fourni dans la requête.
- La requête de l'utilisateur obtient les informations détaillées de l'utilisateur en fonction de l'ID de l'utilisateur. Il accepte l'ID comme paramètre de contexte et un objet utilisateur.
- La requête ALLUSER renvoie les détails de tous les utilisateurs.
Si l'état de l'utilisateur est connecté, l'utilisateur sera un objet; Si l'utilisateur n'est pas connecté, l'utilisateur sera nul. Nous créerons cet utilisateur dans notre mutation.
Dans l'analyseur de mutation, nous avons deux fonctions (registre et loginuseur):
- RegisterUser accepte le nom d'utilisateur, le courrier électronique et le mot de passe de l'utilisateur et utilise ces champs pour créer une nouvelle ligne dans notre base de données. Il convient de noter que nous utilisons le package BCryptJS pour hacher le mot de passe de l'utilisateur à l'aide de BCrypt.hash (mot de passe, 10). JSONWEBToken.sign Signe de manière synchrone la charge utile donnée à une chaîne de jeton Web JSON (dans ce cas ID utilisateur et e-mail). Enfin, RegisterUser renverra la chaîne JWT et le profil utilisateur en cas de succès; Si une erreur se produit, un message d'erreur sera renvoyé.
- La connexion accepte les e-mails et le mot de passe et vérifie si ces détails correspondent aux détails fournis. Tout d'abord, nous vérifions si la valeur de messagerie existe déjà quelque part dans la base de données des utilisateurs.
<code>models.User.findOne({ where: { email }}) if (!user) { throw new Error('No user with that email') }</code>
Ensuite, nous utilisons la méthode Bcrypt.Compare de Bcrypt pour vérifier si le mot de passe correspond.
<code>const isValid = await bcrypt.compare(password, user.password) if (!isValid) { throw new Error('Incorrect password') }</code>
Ensuite, comme nous l'avons fait dans RegisterUser auparavant, nous utilisons JSONWEBToken.Sign pour générer la chaîne JWT. La mutation de connexion renvoie les token et les objets utilisateur.
Ajoutons maintenant JWT_SECRET à notre fichier .env.
<code>JWT_SECRET=一个非常长的秘密</code>
serveur
Enfin, c'est le serveur! Créez un serveur.js dans le dossier racine du projet et collez ce qui suit:
<code>const { ApolloServer } = require('apollo-server') const jwt = require('jsonwebtoken') const typeDefs = require('./schema/schema') const resolvers = require('./resolvers/resolvers') require('dotenv').config() const { JWT_SECRET, PORT } = process.env const getUser = token => { try { if (token) { return jwt.verify(token, JWT_SECRET) } return null } catch (error) { return null } } const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { const token = req.get('Authorization') || '' return { user: getUser(token.replace('Bearer', ''))} }, introspection: true, playground: true }) server.listen({ port: process.env.PORT || 4000 }).then(({ url }) => { console.log(`? Server ready at ${url}`); });</code>
Ici, nous importons le schéma, les résolveurs et JWT et initialisons nos variables d'environnement. Tout d'abord, nous utilisons la vérification pour vérifier le jeton JWT. JWT.Verify accepte le jeton et la clé JWT comme paramètres.
Ensuite, nous créons notre serveur à l'aide d'une instance ApollOserver qui accepte les typedes et les résolveurs.
Nous avons un serveur! Commençons par exécuter du fil de fil dans le terminal.
API tester
Testons maintenant l'API GraphQL à l'aide de GraphQL Playground. Nous devrions pouvoir nous inscrire, se connecter et afficher tous les utilisateurs - y compris les utilisateurs individuels - via ID.
Nous ouvrirons d'abord l'application GraphQL Playground, ou ouvrirons simplement LocalHost: // 4000 dans le navigateur pour y accéder.
Mutation pour les utilisateurs enregistrés
<code>mutation { registerUser(username: "Wizzy", email: "[email protected]", password: "wizzyekpot" ){ token } }</code>
Nous devrions obtenir des résultats comme ceci:
<code>{ "data": { "registerUser": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzAwLCJleHAiOjE2MzA3OTc5MDB9.gmeynGR9Zwng8cIJR75Qrob9bovnRQT242n6vfBt5PY" } } }</code>
Mutation de connexion
Maintenant, connectons avec les détails de l'utilisateur que nous venons de créer:
<code>mutation { login(email:"[email protected]" password:"wizzyekpot"){ token } }</code>
Nous devrions obtenir des résultats comme ceci:
<code>{ "data": { "login": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc" } } }</code>
merveilleux!
Requête pour les utilisateurs individuels
Pour interroger un seul utilisateur, nous devons passer le jeton utilisateur en tant qu'en-tête d'autorisation. Accédez à l'onglet En-tête HTTP.
... et collez ce contenu dans:
<code>{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc" }</code>
Voici la requête:
<code>query myself{ me { id email username } }</code>
Nous devrions obtenir des résultats comme ceci:
<code>{ "data": { "me": { "id": 15, "email": "[email protected]", "username": "Wizzy" } } }</code>
Super! Maintenant, faisons l'utilisateur par ID:
<code>query singleUser{ user(id:15){ id email username } }</code>
Voici une requête pour obtenir tous les utilisateurs:
<code>{ allUsers{ id username email } }</code>
Résumer
L'authentification est l'une des tâches les plus difficiles lors de la création d'un site Web qui nécessite une authentification. GraphQL nous permet de créer une API d'authentification complète en utilisant un seul point de terminaison. SECELIZE ORM facilite la création de relations avec les bases de données SQL que nous n'avons guère à nous soucier de notre modèle. Il convient également de noter que nous n'avons pas besoin de bibliothèques de serveurs HTTP (comme Express), mais utilisons Apollo GraphQL comme middleware. Apollo Server 2 nous permet désormais de créer nos propres serveurs GraphQL indépendants de la bibliothèque!
Veuillez vérifier le code source de ce didacticiel sur GitHub.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Dans cet article, Blackle Mori vous montre quelques-uns des hacks trouvés tout en essayant de repousser les limites du support HTML de Cohost. Utilisez-les si vous osez, de peur que vous soyez également étiqueté un criminel CSS.

Les curseurs personnalisés avec CSS sont excellents, mais nous pouvons faire passer les choses au niveau supérieur avec JavaScript. À l'aide de JavaScript, nous pouvons passer entre les états du curseur, placer du texte dynamique dans le curseur, appliquer des animations complexes et appliquer des filtres.

Les animations CSS interactives avec des éléments se ricochent semblent plus plausibles en 2025. Bien qu'il soit inutile de mettre en œuvre Pong dans CSS, la flexibilité et la puissance croissantes de CSS renforcent le soupçon de Lee selon lequel un jour, ce sera un jour

Conseils et astuces sur l'utilisation de la propriété CSS Back-Filter pour styliser les interfaces utilisateur. Vous apprendrez à superposer des filtres en toile de fond entre plusieurs éléments et à les intégrer à d'autres effets graphiques CSS pour créer des conceptions élaborées.

Eh bien, il s'avère que les fonctionnalités d'animation intégrées de SVG n'ont jamais été obsolètes comme prévu. Bien sûr, CSS et JavaScript sont plus que capables de porter la charge, mais il est bon de savoir que Smil n'est pas mort dans l'eau comme précédemment

Yay, laissez-le saut pour le wat-wrap: joli atterrissage dans la technologie safari aperçu! Mais méfiez-vous qu'il est différent de la façon dont il fonctionne dans les navigateurs de chrome.

Cette mise à jour de CSS-Tricks met en évidence des progrès significatifs dans l'Almanac, des apparitions de podcast récentes, un nouveau guide CSS Counter et l'ajout de plusieurs nouveaux auteurs contribuant un contenu précieux.

La plupart du temps, les gens présentent la fonctionnalité de Tailwind avec l'un des utilitaires à propriété unique de Tailwind (qui modifie une seule déclaration CSS). Lorsqu'il est présenté de cette façon, @Apply ne semble pas du tout prometteur. So évidence


Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Adaptateur de serveur SAP NetWeaver pour Eclipse
Intégrez Eclipse au serveur d'applications SAP NetWeaver.

DVWA
Damn Vulnerable Web App (DVWA) est une application Web PHP/MySQL très vulnérable. Ses principaux objectifs sont d'aider les professionnels de la sécurité à tester leurs compétences et leurs outils dans un environnement juridique, d'aider les développeurs Web à mieux comprendre le processus de sécurisation des applications Web et d'aider les enseignants/étudiants à enseigner/apprendre dans un environnement de classe. Application Web sécurité. L'objectif de DVWA est de mettre en pratique certaines des vulnérabilités Web les plus courantes via une interface simple et directe, avec différents degrés de difficulté. Veuillez noter que ce logiciel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

VSCode Windows 64 bits Télécharger
Un éditeur IDE gratuit et puissant lancé par Microsoft
