Node.js Login System mit Express, JWT & MySQL

In diesem Tutorial bauen wir ein Node.js Login mit Express, JWT und MySQL. Diese RestAPI kannst du dann ganz flexibel an den Frontend anbinden.

Dieses Tutorial ist der erste Teil der zweiteiligen Serie zur Erstellung eines kompletten Login Systems mit Node.js und Vue.js. Dazu nutzen wir Node.js als Backend und Vue.js als Frontend.

Das Tutorial ist in zwei Beiträge aufgeteilt, damit du nicht an ein bestimmtes Frontend Framework gebunden bist, sondern dieses Node Login System, welches wir in diesem Beitrag entwickeln, gleichermaßen mit einem Vue.js, React oder Angular Framework nutzen kannst.

Als Bonus stelle ich dir den kompletten Code in einem Git Repository bereit! 🙂

Wir erstellen eine Node.js Anwendung. Dazu haben wir eine MySQL Datenbank, in der unsere Benutzerdaten gespeichert sind. Alternativ kannst du die Datenbank aber auch durch z.B. eine MongoDB Datenbank ersetzen. Zur Authentifizierung müssen wir diese Daten dann abfragen und können mit Hilfe des JWT (JSON Web Token) Packages eine Session (Sitzung) für den Benutzer eröffnen.

Hier gibt es das Tutorial auch in Videoform:

Was ist eine Rest API?

Eine Rest API stellt die Schnittstelle zwischen Server und Client dar. Über einfache HTTP Anfragen erreichen wir den Server und können programmierte Funktionen ausführen, wie das Authentifizieren eines Benutzers mit zugehörigem Passwort.

Solltest du mit Node.js noch nicht vertraut sein, kannst du dir dieses Node.js Anfänger Tutorial anschauen. Danach hast du alle Grundlagen drauf und kannst dich an Dein Node.js Login System wagen.

1. Abhängigkeiten installieren

Nachdem du ein neues Projekt mit npm init initialisiert hast, können wir die benötigten Abhängigkeiten installieren. Wir benötigen folgende Module:

PackageBeschreibung
expressDamit erstellen wir unseren eigenen Webserver für unsere Rest API
mysqlZum Lesen/Schreiben in unsere Datenbank
uuidZum Erstellen von IDs für spätere Benutzer
bcryptjs (Achtung: nicht bcrypt)Zum Ver-/Entschlüsseln der Passwörter
jsonwebtokenZur Handhabung der Nutzer-Sessions
corsDamit wir die Rest API von unserer Website aufrufen können.
dotenvVerwalten von Umgebungsvariablen

Diese Module installieren wir über folgenden CLI Befehl npm install express mysql uuid bcryptjs jsonwebtoken cors dotenv.

Damit du einen besser Überblick hast, wo welche Dateien abzulegen sind, hier eine kleine Übersicht:

├── lib
│   └── db.js
├── middleware
│   └── users.js
├── routes
│   └── router.js
├── .env
└── index.js

2. MySQL-Datenbank Schema erstellen

Als Datenbank-Engine nutze ich XAMPP, damit ich mir eine eigene Datenbank lokal hosten kann. Natürlich kannst du auch jede andere (Remote-) Datenbank verwenden.

Für unser Login System benötigen wir nur eine Tabelle nach folgendem Schema:

ER-Modell der "users" Tabelle
ER-Modell der „users“ Tabelle

In der Datenbank sieht unsere Tabelle dann folgendermaßen aus:

phpMyAdmin Ansicht der "users" Tabelle
phpMyAdmin Ansicht der „users“ Tabelle

Damit wir auch über unsere Node.js Anwendung auf diese Verbindung zugreifen können, erstellen wir eine eigene Klasse Datei, die wir später in unserem Router einbinden.

// lib/db.js

const mysql = require('mysql');

const connection = mysql.createConnection({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  database: process.env.DB_NAME,
  password: process.env.DB_PASSWORD,
});

connection.connect();
module.exports = connection;

Sicherheitsrelevante Informationen, wie Passwörter, PINs oder Tokens solltest du niemals direkt im Code speichern! Daher legt man für solche Daten Umgebungsvariablen an. Das sind Variablen, die in den verschiedenen Stages deiner Anwendung unterschiedlich konfiguriert sein können und auch niemals in einem Repository gespeichert werden.

Um diese Platzhalter nun mit dem richtigen Inhalt zu füllen, legen wir die Datei .env an. Beachte den Punkt am Anfang. Dort legen wir unsere vier verwendeten Variablen an:

DB_HOST=localhost
DB_USER=root
DB_PASSWORD=******
DB_NAME=node-login-tutorial

Wenn du deinen Code in einem Repository verwaltest, solltest du unbedingt die Datei .env in deiner .gitignore einfügen.

3. Express Router aufsetzen und Routen erstellen

Unsere Einstiegsdatei ist die index.js und beinhaltet das Starten unsere Webservers und die Einbindung der Routen, die wir in der Datei routes/router.js definieren.

// index.js

const express = require('express');
const app = express();
const cors = require('cors');

require('dotenv').config();
const PORT = process.env.PORT || 3000;

app.use(express.json());
app.use(cors());

const router = require('./routes/router.js');
app.use('/api', router);

app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

In der router.js definieren wir unsere Routen und verpacken danach die Logik darin. Grund, wieso wir hier eine extra Datei benutzen ist die Übersichtlichkeit. Wenn Deine Anwendung irgendwann 20 oder noch mehr Routen hat, gibt es ein großes Chaos in der index.js. Deshalb lagern wir unsere Routen aus.

// routes/router.js

const express = require('express');
const router = express.Router();

const bcrypt = require('bcryptjs');
const uuid = require('uuid');
const jwt = require('jsonwebtoken');

const db = require('../lib/db.js');
const userMiddleware = require('../middleware/users.js');

router.post('/sign-up', (req, res, next) => {});

router.post('/login', (req, res, next) => {});

router.get('/secret-route', (req, res, next) => {
  res.send('This is the secret content. Only logged in users can see that!');
});

module.exports = router;

Hier registrieren wir die Route /api/sign-up zum Registrieren und /api/login zum Anmelden. Außerdem haben wir die Route /api/secret-route, diese soll man nur aufrufen können, wenn man angemeldet ist. Aktuell kann diese jeder Benutzer aufrufen. Dazu aber später mehr.

In Zeile 10 binden wir außerdem unsere Datei für die Datenbank Verbindung ein.

Wir binden noch die Datei ../middleware/users.js ein, in der befindet sich der Code um die Anfragen zu verifizieren. Das bedeutet, wir prüfen dort, ob der Benutzer z.B. ein Passwort eingegeben hat und der Benutzername den Richtlinien entspricht. Diese Abfragen schalten wir später als Middleware in den Aufruf unserer Routen.

4. Middleware erstellen (Validierung)

Eine Middleware ist quasi ein kleines Programm, was zwischen zwei Komponenten geschaltet ist. In diesem Fall haben wir zwischen unserem Request und der eigentlichen Registrierung eine Middleware, die die eingegebenen Daten validiert. Für die Registrierung kann eine Validierung wie folgt aussehen:

// middleware/users.js

const jwt = require("jsonwebtoken");

module.exports = {
  validateRegister: (req, res, next) => {
    // username min length 3
    if (!req.body.username || req.body.username.length < 3) {
      return res.status(400).send({
        message: 'Please enter a username with min. 3 chars',
      });
    }
    // password min 6 chars
    if (!req.body.password || req.body.password.length < 6) {
      return res.status(400).send({
        message: 'Please enter a password with min. 6 chars',
      });
    }
    // password (repeat) must match
    if (
      !req.body.password_repeat ||
      req.body.password != req.body.password_repeat
    ) {
      return res.status(400).send({
        message: 'Both passwords must match',
      });
    }
    next();
  }
};

Beim Aufruf unserer /sign-up Route soll unsere Middleware ausgeführt werden. Dazu ändern wie die markierte Zeile wie folgt ab:

// routes/router.js

const express = require('express');
const router = express.Router();

const userMiddleware = require('../middleware/users.js');

router.post('sign-up', userMiddleware.validateRegister, (req, res, next) => {});

router.post('login', (req, res, next) => {});

module.exports = router;

5. Express Routen erstellen

5.1 Register Route umsetzen

Um einen neuen Benutzer in die Datenbank aufzunehmen, müssen wir überprüfen, ob der Benutzername noch nicht existiert. Ist der Benutzer vorhanden, wird eine Fehlermeldung ausgegeben. Ist der Benutzer noch nicht vorhanden, wird mittels unserem Modul bcryptjs, das eingegebene Passwort gehasht (verschlüsselt) und dann alle Daten in die Datenbank eingetragen.

// routes/router.js

router.post('/sign-up', userMiddleware.validateRegister, (req, res, next) => {
  db.query(
    'SELECT id FROM users WHERE LOWER(username) = LOWER(?)',
    [req.body.username],
    (err, result) => {
      if (result && result.length) {
        // error
        return res.status(409).send({
          message: 'This username is already in use!',
        });
      } else {
        // username not in use
        bcrypt.hash(req.body.password, 10, (err, hash) => {
          if (err) {
            return res.status(500).send({
              message: err,
            });
          } else {
            db.query(
              'INSERT INTO users (id, username, password, registered) VALUES (?, ?, ?, now());',
              [uuid.v4(), req.body.username, hash],
              (err, result) => {
                if (err) {
                  return res.status(400).send({
                    message: err,
                  });
                }
                return res.status(201).send({
                  message: 'Registered!',
                });
              }
            );
          }
        });
      }
    }
  );
});

Ist das Eintragen des Benutzers erfolgreich, wird der Statuscode 201 („created“) zurückgegeben und der Funktionsaufruf damit beendet.

Schon mal von Double Opt-In gehört? Dabei werden Bestätigungsmails versendet, um eine Anmeldung zu verifizieren. In diesem Tutorial erfährst du, wie du Double Opt-In in Deine Node.js Anwendung (aufbauend auf diesem Tutorial) einbauen kannst.

5.2 Login Route umsetzen

Neben dem Registrierungsprozess haben wir eine Login Route, um sich für bereits registrierte Benutzer anzumelden. Hier wird der passende Datenbankeintrag anhand des Benutzernamen gesucht. Danach wird das eingegebene mit dem verschlüsselten Passwort aus der Datenbank mit Hilfe von jwt.compare() überprüft. Ein kurzes SQL Query setzt in Zeile 45 das letzt Login Datum/Zeit auf den aktuellen Wert.

// routes/router.js

[...]
router.post('/login', (req, res, next) => {
  db.query(
    `SELECT * FROM users WHERE username = ?;`,
    [req.body.username],
    (err, result) => {
      if (err) {
        return res.status(400).send({
          message: err,
        });
      }
      if (!result.length) {
        return res.status(400).send({
          message: 'Username or password incorrect!',
        });
      }

      bcrypt.compare(
        req.body.password,
        result[0]['password'],
        (bErr, bResult) => {
          if (bErr) {
            return res.status(400).send({
              message: 'Username or password incorrect!',
            });
          }
          if (bResult) {
            // password match
            const token = jwt.sign(
              {
                username: result[0].username,
                userId: result[0].id,
              },
              'SECRETKEY',
              { expiresIn: '7d' }
            );
            db.query(`UPDATE users SET last_login = now() WHERE id = ?;`, [
              result[0].id,
            ]);
            return res.status(200).send({
              message: 'Logged in!',
              token,
              user: result[0],
            });
          }
          return res.status(400).send({
            message: 'Username or password incorrect!',
          });
        }
      );
    }
  );
});

In Zeile 33 und 34 übergeben wir Variablen, die wir im JWT Token „speichern“ möchten. Dadurch haben wir in den geschützten Routen Zugriff auf diese Variablen.

In Zeile 36 musst du einen Key übergeben, mit dem der JWT Token generiert wird, dieser ist später für die Überprüfung wichtig. Hier kannst du einen beliebigen String eingeben.

Außerdem kannst du in Zeile 37 festlegen, wie lange der Token gültig sein soll. Werte wie „1h“ oder „3m“ sind hier gültig. Die einzelnen Werte und Parameter kannst du auch in der Dokumentation nachlesen.

Falls das Passwort falsch ist oder der Benutzername nicht existiert wird eine Fehlermeldung ausgegeben. Diese Meldung ist absichtlich identisch, da ein potentieller Angreifer sonst Informationen über das Existieren von einzelnen Benutzerprofilen bekommen kann.

Bei erfolgreichem Login wird das Benutzerobjekt und der von JWT generierte Token zurückgegeben. Dieser Token ist für alle Routen wichtig, in denen man eingeloggt sein soll. Im Teil 2 (Vue.js Frontend) erfährst du, wie du diesen bei jedem Request übergeben kannst. Wenn du die Rest API mit Postman testest, kannst du den Token mit dem Key „Authorization“ als Value nach folgender Syntax angeben: „Bearer KEY“.

Postman Authorization Header
Postman Authorization Header

5.3 Routen mit Login schützen

Die wichtigsten Routen sind nun fertig. Wir können neue Benutzer hinzufügen und uns mit bestehenden Accounts anmelden. Nun wollen wir noch Routen schützen. Das bedeutet, dass nur angemeldete Benutzer Zugriff darauf haben.

Dazu legen wir in unserer users.js eine neue Middleware an. Hierbei wird der Token aus dem Header des Requests genommen und durch JWT verifiziert.

// middleware/users.js

  [...]
  isLoggedIn: (req, res, next) => {
    if (!req.headers.authorization) {
      return res.status(400).send({
        message: 'Your session is not valid!',
      });
    }
    try {
      const authHeader = req.headers.authorization;
      const token = authHeader.split(' ')[1];
      const decoded = jwt.verify(token, 'SECRETKEY');
      req.userData = decoded;
      next();
    } catch (err) {
      return res.status(400).send({
        message: 'Your session is not valid!',
      });
    }
  }
  [...]

In der markierten Zeile musst du den gleichen Key angeben, mit dem du den JWT bereits generiert hast.

Um nun eine Route zu schützen, bindest du diese Middleware einfach beim Aufruf der Route wie folgt ein:

// routes/router.js

[...]
router.get('/secret-route', userMiddleware.isLoggedIn, (req, res, next) => {
  console.log(req.userData);
  res.send('This is the secret content. Only logged in users can see that!');
});
[...]

In req.userData stehen die Daten die wir im JWT Key abgelegt haben (in diesem Fall username und userId). Damit können wir z.B. bei geschützten Routen benutzerdefinierte Werte aus der Datenbank anhand der userId auslesen.

Bei der Entwicklung einer Rest API kann es zu Fehlern kommen – das ist völlig normal. Oft sind irgendwelche Randfälle nicht bedacht. Wie du diese Testfälle auswählst und diese automatisiert testen kannst, habe ich dir hier zusammengefasst: Rest API richtig testen.

Kompletten Code in Git Repository anschauen

6. Node Login System deployen

Super, dein Node.js Login mit Express, JWT und MySQL ist fertig. Jetzt kannst du dir ein schickes Frontend bauen und dein Backend anbinden.

Wie du deine fertige App dann deployen – also live stellen kannst, habe ich dir in hier beschrieben.

➡️ Hier geht’s zum 2. Teil: Vue.js Login System mit Vuex & Axios

Ähnliche Beiträge
Beteilige dich an der Unterhaltung

25 Kommentare

  1. JB sagt:

    Hallo zusammen, ich habe nun schon einige kleine, wirklich kleine (Hallo Welt etc.) mit Node.js umgesetzt.Leider funktioniert das Login System bei mir nicht. :-(Was kann ich nur tun?Beim Aufruf im Browser (http://127.0.0.1:3000) bekomme ich nur „Cannot GET“.Sollte da nicht etwas mehr passieren? Für Hilfe oder auch einen kleinen wegweiser wäre ich dankbar.

    1. Lorenz sagt:

      Hi! Hast du dir auch mal das Video dazu angeschaut? (https://www.youtube.com/watch?v=41pbn2I_XkY&ab_channel=webdeasy) Vielleicht findest du dort den Unterschied? Dein Programm scheint die Route nicht zu erkennen. Sind Fehlermeldungen in der Konsole? 

      1. JB sagt:

        Hallo Lorenz,danke für deine Antwort, ich hätte wohl die Fehler mehr beschreiben sollen.Die Konsole von Node zeigt keine Fehler aber wie erwartet „Server running on port 3000″Die Browser Konsole hat einen Fehler „GET http://localhost:3000/ 404 (Not Found)“Das Video hatte ich mir auch schon angesehen, leider finde finde ich keinen Unterschied zu meinen Projekt-Dateien.

  2. Dimitry T sagt:

    Hi, wie kann ich Kapitel 8, LoggedIn mit Postman testen. Ich bekomme immer { „msg“: „Your session is not valid!“}

    1. Lorenz sagt:

      Hi, gute Frage! Das Thema habe ich in diesem Artikel beschrieben, das sollte dir helfen: Rest API testen (Token übergeben)

  3. Florian sagt:

    Danke für dieses tolle Tutorial! Könntest du uns noch erklären, wie man ein Logout via /logout erstellt?

    1. Lorenz sagt:

      Danke für das Lob! Den Logout kannst du clientseitig implementieren. In der Vue-Version findest du in der store.js die entsprechende Funktion: https://webdeasy.de/login-system-mit-nodejs-vue-js-vuex-part-2-2/#init-vuex

  4. J sagt:

    Hallo, ich habe in den letzten vier Tagen versucht diesen Code zu übernehmen.Abschrieben war nicht das Problem, auch die Korrekturen, die erst am ende des Videos erwähnt wurden habe ich durchgeführt.Doch ich bekomme es nicht hin. Ich bekomme jede menge Syntax Fehler.Die gesamten Lauffähigen Dateien wären mir eine große Hilfe um die gesammten Fehler zu finden.GrußJ

    1. Lorenz sagt:

      Hi, den kompletten Code findest du hier auf der Seite. Am Anfang von jedem Codeblock steht ein Kommentar aus welcher Datei der Code ist (z.B. // routes/router.js). Das ist fast 1:1 der Code aus dem Video.

      Viele Grüße

      LH

  5. Edi sagt:

    Hi,die grössten Teil habe ich mitmachen können. Dein Authetifizierung habe ich meine Todo-app eingebaut. Neue user registrieren funktioniert, auch bei falsche Eingaben zeigt es richtige Fehler Meldungen. Login funktioniert auch ABER wenn ich die falsche Daten bei Login eingebe, werden keine Meldungen angezeigt. Es landet immer in catch-teil!! Wo liege ich falsch?async login() { try { const credentials = { username: this.username, password: this.password }; const response = await AuthService.login(credentials); this.msg = response.message; console.log(„Message“ + response.msg + response.user) const token = response.token; const user = response.user; this.$store.dispatch(‚login‘, { token, user }); this.$router.push(‚/‘); } catch (error) { console.log(„something is wrong. Message: “ + this.msg) this.msg = error.response.data.msg; }

    1. Lorenz sagt:

      Lass dir mal vor await AuthService.login(credentials) das credentials ausgeben. Eventuell wurden dort nicht alle Werte korrekt gesetzt.  Vielleicht hast du auch in der AuthService.js die URL falsch gesetzt. Lass dir Schritt für Schritt Sachen ausgeben, dann wirst du den Fehler finden.

      Meld dich falls Du nicht weiter kommst

      Viele Grüße
      Lorenz

  6. Alexander Wottschel sagt:

    Danke für die schöne Anleitung. Zwar für einen Laien immer noch ziemlich wild, was es alles braucht, um eine Node.js- Anwendung auf dem Server zu laufen zu bringen, aber die meisten anderen Anleitungen fand ich noch komplizierter.
    Nun habe ich das ausprobiert und kriege am Ende einen Fehler, sobald ich die Routen einbinden will.

    in der index.js sind ja folgende Zeilen:
    const router = require(‚./routes/router.js‘);
    app.use(‚/api‘, router);

    an der Stelle überrascht mich der Pfad „/api“. Dieser wurde bisher doch nirgends erwähnt. Wieso taucht dieser hier auf einmal auf? Was ist da drin? wenn ich das richtig interpretiere, muss SignIn und Login dort rein? Ich glaube bei mir passt mit dem Pfaden etwas nicht. Cool wäre ein Screenshot, wie das in etwa alles aussieht bis hierher.

    Hier mein aktueller Fehler und nun versuche ich mich etwas einzulesen, um was zu verstehen.

    Server running on port 3000
    events.js:292
    throw er; // Unhandled ‚error‘ event
    ^

    Error: getaddrinfo ENOTFOUND localhost
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:67:26)
    ——————–
    at Protocol._enqueue (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/protocol/Protocol.js:144:48)
    at Protocol.handshake (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/protocol/Protocol.js:51:23)
    at Connection.connect (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/Connection.js:116:18)
    at Object. (/Users/codeagent/_workspace/root-tree/lib/db.js:8:12)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    Emitted ‚error‘ event on Connection instance at:
    at Connection._handleProtocolError (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/Connection.js:423:8)
    at Protocol.emit (events.js:315:20)
    at Protocol._delegateError (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/protocol/Protocol.js:398:10)
    at Handshake. (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/protocol/Protocol.js:153:12)
    at Handshake.emit (events.js:315:20)
    at Handshake.Sequence.end (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/protocol/sequences/Sequence.js:78:12)
    at Protocol.handleNetworkError (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/protocol/Protocol.js:369:14)
    at Connection._handleNetworkError (/Users/codeagent/_workspace/root-tree/node_modules/mysql/lib/Connection.js:418:18)
    at Socket.emit (events.js:315:20)
    at emitErrorNT (internal/streams/destroy.js:106:8) {
    errno: -3008,
    code: ‚ENOTFOUND‘,
    syscall: ‚getaddrinfo‘,
    hostname: ‚localhost‘,
    fatal: true
    }

    1. Lorenz sagt:

      Hi Alexander!

      Der Fehler scheint von der Datenbank Verbindung (mysql) zu kommen. Schau mal, ob der Datenbank Part richtig ist und vor allem: ob die Zugangsdaten stimmen. Kommentiere doch bis die Frage mit den Routen geklärt ist die Zeile 10 (const db = require('../lib/db.js');) noch mal aus, damit der Fehler da nicht reinfunkt.

      Die Routen die wir erstellen lauten: http://localhost:3000/api/login, http://localhost:3000/api/sign-up und http://localhost:3000/api/secret-rout (bzw. statt localhost die Adresse des Servers). Mit dem Aufruf
      const router = require(‚./routes/router.js‘);
      app.use(‚/api‘, router);
      lagern wir den Code einfach nur in die router.js aus. Daraus ergibt sich dann eben auch der Pfad mit /api davor. Das ist aber einfach nur Geschmacksache. Wenn Deine Routen http://localhost:3000/login so aussehen sollen, ohne /api kannst Du einfach app.use(‚/‘, router); schreiben.

      Hoffe das Ganze ist jetzt etwas verständlicher 🙂

      Viele Grüße
      LH

      1. Alexander Wottschel sagt:

        oh man, den Fehler hätte man auch googeln können. Danke, klappt nun 🙂

        1. Lorenz sagt:

          Kein Problem, Hauptsache es geht jetzt 😉

  7. Jonas Mahdalicek sagt:

    Hi,

    habe das Tutorial nachgemacht, leider funktioniert es bei mir nicht. Es kommt folgender fail log:

    0 info it worked if it ends with ok
    1 verbose cli [
    1 verbose cli 'C:\\Program Files\\nodejs\\node.exe',
    1 verbose cli 'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
    1 verbose cli 'start'
    1 verbose cli ]
    2 info using npm@6.14.11
    3 info using node@v14.16.0
    4 verbose run-script [ 'prestart', 'start', 'poststart' ]
    5 info lifecycle server-backend@0.0.0~prestart: server-backend@0.0.0
    6 info lifecycle server-backend@0.0.0~start: server-backend@0.0.0
    7 verbose lifecycle server-backend@0.0.0~start: unsafe-perm in lifecycle true
    8 verbose lifecycle server-backend@0.0.0~start: PATH: C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin;C:\Users\herbe\WebstormProjects\Server_Backend\node_modules\.bin;C:\Users\herbe\WebstormProjects\Server_Backend\node_modules\.bin;C:\ProgramData\Oracle\Java\javapath;C:\Python27\;C:\Python27\Scripts;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Java\jdk1.8.0_201\bin;C:\Program Files\apache-maven-3.6.0-bin\apache-maven-3.6.0\bin;C:\Program Files\PuTTY\;C:\ProgramData\chocolatey\bin;C:\Program Files\Git\cmd;C:\Program Files\nodejs\;C:\Users\herbe\AppData\Local\Microsoft\WindowsApps;C:\Users\herbe\AppData\Local\Programs\Microsoft VS Code\bin;C:\Program Files (x86)\Nmap;C:\Users\herbe\AppData\Local\gitkraken\bin;C:\Users\herbe\AppData\Roaming\npm
    9 verbose lifecycle server-backend@0.0.0~start: CWD: C:\Users\herbe\WebstormProjects\Server_Backend
    10 silly lifecycle server-backend@0.0.0~start: Args: [ '/d /s /c', 'node ./bin/www' ]
    11 silly lifecycle server-backend@0.0.0~start: Returned: code: 1 signal: null
    12 info lifecycle server-backend@0.0.0~start: Failed to exec start script
    13 verbose stack Error: server-backend@0.0.0 start: `node ./bin/www`
    13 verbose stack Exit status 1
    13 verbose stack at EventEmitter. (C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\index.js:332:16)
    13 verbose stack at EventEmitter.emit (events.js:315:20)
    13 verbose stack at ChildProcess. (C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\lib\spawn.js:55:14)
    13 verbose stack at ChildProcess.emit (events.js:315:20)
    13 verbose stack at maybeClose (internal/child_process.js:1048:16)
    13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:288:5)
    14 verbose pkgid server-backend@0.0.0
    15 verbose cwd C:\Users\herbe\WebstormProjects\Server_Backend
    16 verbose Windows_NT 10.0.18363
    17 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "start"
    18 verbose node v14.16.0
    19 verbose npm v6.14.11
    20 error code ELIFECYCLE
    21 error errno 1
    22 error server-backend@0.0.0 start: `node ./bin/www`
    22 error Exit status 1
    23 error Failed at the server-backend@0.0.0 start script.
    23 error This is probably not a problem with npm. There is likely additional logging output above.
    24 verbose exit [ 1, true ]

    Hätte da jemand eine Ahnung was da nicht funktioniert?
    Danke im Voraus.
    Lg

    1. Lorenz sagt:

      Hi, wann tritt das Problem auf?

  8. Markus sagt:

    Hi,

    klasse Tutorial. Für mich als Einsteiger in Node.js gut und nachvollziehbar beschrieben.
    Eine Frage habe ich dennoch, in der users.js gab es bei isLoggedIn einen Fehler, weil jwt nicht deklariert war.
    Nachdem ich das nachgeholt habe, funktionierte auch der Aufruf einer URL als eingeloggter User.
    Fehlt das im Tutorial oder hab ich was falsch gemacht?

    Liebe Grüße,
    Markus

    1. Lorenz sagt:

      Hallo, danke! Da hat es sich tatsächlich um einen Fehler gehandelt, hab es ergänzt. Danke für den Hinweis 🙂

      Viele Grüße
      Lorenz

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

bold italic underline strikeThrough
insertOrderedList insertUnorderedList outdent indent
removeFormat
createLink unlink
code

Das könnte dich auch interessieren