


Erstellen Sie unsere eigene Authentifizierungs -API mit NodeJS und GraphQL
Die Authentifizierung ist eine der schwierigsten Aufgaben für Entwickler, die in GraphQL neu sind. Es gibt viele technische Überlegungen, darunter die Auswahl eines ORM, das einfach festgelegt ist, wie man ein sicheres Token- und Hash -Passwort generiert, und sogar die HTTP -Bibliothek und die Verwendung.
Dieser Artikel konzentriert sich auf die lokale Authentifizierung . Dies ist wahrscheinlich die beliebteste Möglichkeit für moderne Websites, die Authentifizierung zu bewältigen, die durch Anfragen von E -Mails und Kennwörtern der Benutzer erreicht wird (im Gegensatz zur Verwendung von Google -Authentifizierung).
Darüber hinaus verwendet dieser Artikel Apollo Server 2, JSON Web Tokens (JWT) und FEKURISE ORM, um eine Node.js -Authentifizierungs -API zu erstellen.
Authentifizierungsverarbeitung
Melden Sie sich beim System an:
- Die Authentifizierung identifiziert oder authentifiziert Benutzer.
- Autorisiert die Überprüfung von Routen (oder Teilen der Anwendung), auf die ein authentifizierter Benutzer zugreifen kann.
Die Schritte zur Implementierung dieses Prozesses sind wie folgt:
- Benutzer registrieren sich mit Passwort und E -Mail.
- Die Anmeldeinformationen des Benutzers werden in der Datenbank gespeichert.
- Nach Abschluss der Registrierung wird der Benutzer auf die Anmeldeseite umgeleitet.
- Nach der Authentifizierung erhält dem Benutzer Zugriff auf eine bestimmte Ressource.
- Der Status des Benutzers wird in jedem Browserspeichermedium (z. B. Lokalstor, Cookies, Sitzungen) oder in einem JWT gespeichert.
Voraussetzungen
Bevor Sie tiefer gehen, sind hier einige Schritte, die Sie befolgen müssen.
- Node.js 6 oder höher
- Garn (empfohlen) oder NPM
- GraphQL -Spielplatz
- Grundlagen von GraphQL und Node.js
- … Ein Herz, das Wissen sucht!
Abhängigkeiten
Hier ist eine lange Liste, fangen wir an:
- Apollo Server : Ein Open -Source -GraphQL -Server, der mit einem beliebigen Typ von GraphQL -Client kompatibel ist. In diesem Projekt werden wir Express nicht als unseren Server verwenden. Stattdessen nutzen wir die Funktionen des Apollo -Servers, unsere GraphQL -API aufzudecken.
- BCryptjs : Wir möchten das Benutzerkennwort in unsere Datenbank haben . Deshalb werden wir Bcrypt verwenden. Es basiert auf der GetRandomvalues -Schnittstelle der Web Crypto -API, um sichere Zufallszahlen zu erhalten.
- DOTENV : Wir werden dotenv verwenden, um Umgebungsvariablen aus unserer .Env -Datei zu laden.
- JSONWEBTOKE : Nachdem sich der Benutzer angemeldet hat, enthält jede nachfolgende Anfrage eine JWT, sodass der Benutzer auf die Routen, Dienste und Ressourcen zugreifen kann, die die Verwendung des Tokens zulässt. JSONWEBTOKE wird verwendet, um JWTs zu generieren, die zur Überprüfung der Identität des Benutzers verwendet werden.
- Nodemon : Ein Tool, mit dem notenbasierte Anwendungen entwickelt werden können, indem Knotenanwendungen automatisch neu gestartet werden, wenn eine Verzeichnisänderung erkannt wird. Wir möchten nicht, dass der Server jedes Mal heruntergefahren und gestartet wird, wenn sich der Code ändert. Nodemon prüft jedes Mal Änderungen in unserer Anwendung und startet den Server automatisch neu.
- MySQL2 : SQL Client von Node.js. Wir brauchen es, um eine Verbindung zu unserem SQL -Server herzustellen, damit wir die Migration ausführen können.
- Sequelize : Sequelize ist ein vielversprechender Knoten, der in Postgres, MySQL, Mariadb, SQLite und Microsoft SQL Server verwendet wird. Wir werden ein Folge verwenden, um unsere Migrationen und Modelle automatisch zu generieren.
- Folgene CLI : Wir werden die Folge -CLI verwenden, um den Befehl sequelize auszuführen. Installieren Sie es weltweit im Terminal mit Garn-Add-Global Sequelize-Cli.
Einrichten der Verzeichnisstruktur und Entwicklungsumgebung
Lassen Sie uns ein brandneues Projekt erstellen. Erstellen Sie einen neuen Ordner und erstellen Sie Folgendes darin:
<code>yarn init -y</code>
Das Flag -y bedeutet, dass wir für alle Probleme mit dem Garn -Init -Problem Ja auswählen und den Standardwert verwenden.
Wir sollten auch eine Paket.json -Datei in den Ordner platzieren. Installieren wir also die Projektabhängigkeiten:
<code>yarn add apollo-server bcryptjs dotenv jsonwebtoken nodemon sequelize sqlite3</code>
Als nächstes fügen wir Babel zu unserer Entwicklungsumgebung hinzu:
<code>yarn add babel-cli babel-preset-env babel-preset-stage-0 --dev</code>
Lassen Sie uns nun Babel konfigurieren. Run Touch .babelRC im Terminal. Dadurch wird eine Babel -Konfigurationsdatei erstellt und geöffnet, in der wir Folgendes hinzufügen:
<code>{ "presets": ["env", "stage-0"] }</code>
Es wäre sogar noch besser, wenn unsere Server Daten starten und migrieren. Wir können dies automatisch tun, indem wir Package.json mit den folgenden aktualisieren:
<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>
Hier ist unsere aktuelle komplette Paket.json -Datei:
<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>
Nachdem unsere Entwicklungsumgebung eingerichtet ist, wechseln wir in die Datenbank, wir werden dort Dinge speichern.
Datenbankeinstellungen
Wir werden MySQL als unsere Datenbank verwenden und FEQUELIZE ORM für die relationale Zuordnung verwenden. Fequelize Init ausführen (vorausgesetzt, Sie haben es zuvor global installiert). Dieser Befehl sollte drei Ordner erstellen: /config /models und /migrationen. Zu diesem Zeitpunkt bildet sich unsere Projektverzeichnisstruktur.
Konfigurieren wir unsere Datenbank. Erstellen Sie zunächst eine .env -Datei im Projektroot -Verzeichnis und fügen Sie Folgendes ein:
<code>NODE_ENV=development DB_HOST=localhost DB_USERNAME= DB_PASSWORD= DB_NAME=</code>
Gehen Sie dann in den /Konfigurationsordner, den wir gerade erstellt haben, und benennen Sie die darin config.json -Datei in config.js um. Geben Sie dann den folgenden Code hinein:
<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>
Hier lesen wir die Datenbankdetails, die wir in der .Env -Datei festgelegt haben. process.env ist eine globale Variable, die vom Knoten injiziert wird, um den aktuellen Stand der Systemumgebung darzustellen.
Lassen Sie uns unsere Datenbankdetails mit den entsprechenden Daten aktualisieren. Öffnen Sie die SQL -Datenbank und erstellen Sie eine Tabelle mit dem Namen GraphQL_Auth. Ich benutze Laragon als meinen lokalen Server und verwende PHPMYADMIN, um die Datenbanktabellen zu verwalten.
Unabhängig davon, was Sie verwenden, müssen wir die .Env -Datei mit den neuesten Informationen aktualisieren:
<code>NODE_ENV=development DB_HOST=localhost DB_USERNAME=graphql_auth DB_PASSWORD= DB_NAME=</code>
Konfigurieren wir Folgen. Erstellen Sie eine .sequelizerc -Datei im Stammverzeichnis des Projekts und fügen Sie Folgendes ein:
<code>const path = require('path') module.exports = { config: path.resolve('config', 'config.js') }</code>
Integrieren wir jetzt unsere Konfiguration in das Modell. Gehen Sie zu Index.js in /Models Ordner und bearbeiten Sie die Konfigurationsvariable.
<code>const config = require(__dirname '/../../config/config.js')[env]</code>
Schließlich schreiben wir unser Modell. Für dieses Projekt benötigen wir ein Benutzermodell. Verwenden wir das Folgen, um das Modell automatisch zu generieren. Hier ist, was wir im Terminal laufen müssen, um es einzurichten:
<code>sequelize model:generate --name User --attributes username:string,email:string,password:string</code>
Bearbeiten wir das Modell, das es für uns erstellt. Gehen Sie zu user.js im Ordner /Models und fügen Sie Folgendes ein:
<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>
Hier erstellen wir Eigenschaften und Felder für Benutzernamen, E -Mails und Passwörter. Lassen Sie uns die Migration durchführen, um Änderungen in unserem Schema zu verfolgen:
<code>yarn migrate</code>
Lassen Sie uns nun das Muster und den Parser schreiben.
Integrieren Sie Schema und Parser in den GraphQL -Server
In diesem Abschnitt werden wir unsere Muster definieren, Parser -Funktionen schreiben und sie unserem Server aussetzen.
Modell
Erstellen Sie im SRC -Ordner einen neuen Ordner mit dem Namen /Schema und erstellen Sie eine Datei namens Schema.js. Fügen Sie den folgenden Code ein:
<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>
Hier importieren wir GraphQl-Tag von Apollo-Server. Apollo Server muss unser Muster mit GQL einwickeln.
Parser
Erstellen Sie im SRC -Ordner einen neuen Ordner mit dem Namen /Resolver und erstellen Sie eine Datei namens Resolver.js darin. Fügen Sie den folgenden Code ein:
<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>
Es gibt viel Code, mal sehen, was dort los ist.
Zuerst importieren wir unser Modell, Bcrypt und JsonWebtoken und initialisieren dann unsere Umgebungsvariablen.
Als nächstes kommt die Parser -Funktion. Im Abfrage -Parser haben wir drei Funktionen (ich, Benutzer und Analustierer):
- Ich fordere detaillierte Informationen über den derzeit angemeldeten Benutzer ab. Es akzeptiert Benutzerobjekte als Kontextparameter. Der Kontext wird verwendet, um Zugriff auf unsere Datenbank zu gewährleisten, mit der Benutzerdaten über die in der Abfrage bereitgestellte ID geladen werden.
- Die Benutzerabfrage erhält die detaillierten Informationen des Benutzers basierend auf der ID des Benutzers. Es akzeptiert ID als Kontextparameter und ein Benutzerobjekt.
- Die Anbieterabfrage gibt die Details aller Benutzer zurück.
Wenn der Benutzerstatus angemeldet ist, ist der Benutzer ein Objekt. Wenn der Benutzer nicht angemeldet ist, ist der Benutzer null. Wir werden diesen Benutzer in unserer Mutation erstellen.
Im Mutation -Parser haben wir zwei Funktionen (RegisterUser und Loginuser):
- RegisterUser akzeptiert den Benutzernamen, die E -Mail und das Passwort des Benutzers und verwendet diese Felder, um eine neue Zeile in unserer Datenbank zu erstellen. Es ist zu beachten, dass wir das Bcryptjs -Paket verwenden, um das Kennwort des Benutzers mit bcrypt.hash (Passwort, 10) zu hasht. JSONWEBTOKE.Sign Synchron unterzeichnet die angegebene Nutzlast an eine JSON -Web -Token -Zeichenfolge (in diesem Fall Benutzer -ID und E -Mail). Schließlich gibt RegisterUser das JWT -String und das Benutzerprofil zurück, wenn er erfolgreich ist. Wenn ein Fehler auftritt, wird eine Fehlermeldung zurückgegeben.
- Login akzeptiert E -Mail und Passwort und überprüft, ob diese Details mit den angegebenen Details übereinstimmen. Zunächst überprüfen wir, ob der E -Mail -Wert bereits irgendwo in der Benutzerdatenbank vorhanden ist.
<code>models.User.findOne({ where: { email }}) if (!user) { throw new Error('No user with that email') }</code>
Anschließend verwenden wir die bcrypt -bcrypt.comPare -Methode, um zu überprüfen, ob das Kennwort übereinstimmt.
<code>const isValid = await bcrypt.compare(password, user.password) if (!isValid) { throw new Error('Incorrect password') }</code>
Dann verwenden wir wie in RegisterUser zuvor JsonWebtoken.sign, um die JWT -String zu generieren. Die Login -Mutation gibt Token und Benutzerobjekte zurück.
Fügen wir jetzt jwt_secret zu unserer .env -Datei hinzu.
<code>JWT_SECRET=一个非常长的秘密</code>
Server
Schließlich ist es der Server! Erstellen Sie einen Server.js im Stammordner des Projekts und fügen Sie Folgendes ein:
<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>
Hier importieren wir Schema, Resolver und JWT und initialisieren unsere Umgebungsvariablen. Zunächst verwenden wir Verify, um das JWT -Token zu überprüfen. Jwt.Verify akzeptiert Token und JWT -Schlüssel als Parameter.
Als nächstes erstellen wir unseren Server mithilfe einer Apolloserver -Instanz, die TypedeFs und Resolver akzeptiert.
Wir haben einen Server! Beginnen wir es, indem wir Garn Dev im Terminal ausführen.
Test API
Testen wir nun die GraphQL -API mit dem GraphQL -Spielplatz. Wir sollten in der Lage sein, alle Benutzer - einschließlich einzelner Benutzer - über ID zu registrieren, anzumelden und anzeigen.
Wir öffnen zuerst die GraphQL -Spielplatz -App oder einfach Localhost: // 4000 im Browser, um darauf zuzugreifen.
Mutation für registrierte Benutzer
<code>mutation { registerUser(username: "Wizzy", email: "[email protected]", password: "wizzyekpot" ){ token } }</code>
Wir sollten solche Ergebnisse erzielen:
<code>{ "data": { "registerUser": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzAwLCJleHAiOjE2MzA3OTc5MDB9.gmeynGR9Zwng8cIJR75Qrob9bovnRQT242n6vfBt5PY" } } }</code>
Login -Mutation
Melden wir uns nun mit den gerade erstellten Benutzerdetails an:
<code>mutation { login(email:"[email protected]" password:"wizzyekpot"){ token } }</code>
Wir sollten solche Ergebnisse erzielen:
<code>{ "data": { "login": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc" } } }</code>
wunderbar!
Abfrage für einzelne Benutzer
Um einen einzelnen Benutzer abzufragen, müssen wir das Benutzer -Token als Autorisierungsheader übergeben. Gehen Sie zur Registerkarte HTTP Header.
... und fügen Sie diesen Inhalt in: ein.
<code>{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc" }</code>
Hier ist die Frage:
<code>query myself{ me { id email username } }</code>
Wir sollten solche Ergebnisse erzielen:
<code>{ "data": { "me": { "id": 15, "email": "[email protected]", "username": "Wizzy" } } }</code>
Großartig! Lassen Sie uns nun den Benutzer per ID erhalten:
<code>query singleUser{ user(id:15){ id email username } }</code>
Hier ist eine Abfrage, um alle Benutzer zu bekommen:
<code>{ allUsers{ id username email } }</code>
Zusammenfassen
Die Authentifizierung ist eine der schwierigsten Aufgaben beim Erstellen einer Website, für die Authentifizierung erforderlich ist. Mit GraphQL können wir eine vollständige Authentifizierungs -API mit nur einem Endpunkt erstellen. Durch das Folgen von ORM können Sie Beziehungen zu SQL -Datenbanken so einfach erstellen, dass wir uns um unser Modell kaum Sorgen machen müssen. Es ist auch erwähnenswert, dass wir keine HTTP -Serverbibliotheken (wie Express) benötigen, sondern Apollo GraphQL als Middleware verwenden. Mit Apollo Server 2 können wir nun unsere eigenen bibliotheksunabhängigen GraphQL-Server erstellen!
Bitte überprüfen Sie den Quellcode für dieses Tutorial auf GitHub.
Das obige ist der detaillierte Inhalt vonErstellen Sie unsere eigene Authentifizierungs -API mit NodeJS und GraphQL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Haben Sie jemals einen Countdown -Timer für ein Projekt benötigt? Für so etwas ist es möglicherweise natürlich, nach einem Plugin zu greifen, aber es ist tatsächlich viel mehr

Alles, was Sie schon immer über Datenattribute in HTML, CSS und JavaScript wissen wollten.

Eine Sache, die mich auf die Liste der Funktionen für Lea Verou im Einklang mit Conic-Gradient () -Polyfill auffiel, war das letzte Element:

Zu Beginn eines neuen Projekts erfolgt die SASS -Zusammenstellung im Blinzeln eines Auges. Dies fühlt sich gut an, besonders wenn es mit Browsersync kombiniert ist, das nachlädt

Versuchen wir, hier einen Begriff zu prägen: "Statischer Formanbieter". Sie bringen Ihre HTML

Mit der Inline-Template-Anweisung können wir reichhaltige Vue-Komponenten als fortschreitende Verbesserung gegenüber vorhandenem WordPress-Markup erstellen.

PHP -Vorlagen erhält oft einen schlechten Rap für die Erleichterung von unterdurchschnittlichem Code - aber das muss nicht der Fall sein. Schauen wir uns an, wie PHP -Projekte eine Basis durchsetzen können

Jedes Mal, wenn ich ein neues Projekt starte, organisiere ich den Code, den ich in drei Typen oder Kategorien betrachte, wenn Sie möchten. Und ich denke, diese Typen können auf angewendet werden
