Passport mit Sequelize und MySQL verwenden
() translation by (you can also view the original English article)
Sequelize ist ein auf Versprechen basierendes Node.js-ORM. Es kann mit PostgreSQL, MySQL, MariaDB, SQLite und MSSQL verwendet werden. In diesem Tutorial implementieren wir die Authentifizierung für Benutzer einer Web-App. Und wir werden Passport, die beliebte Authentifizierungs-Middleware für Node, zusammen mit Sequelize und MySQL verwenden, um die Benutzerregistrierung und -anmeldung zu implementieren.
Einstieg
Stellen Sie sicher, dass Folgendes auf Ihrem Computer installiert ist:
- Node
- MySQL
Für dieses Tutorial verwenden wir Node.js zusammen mit Express, also beginnen wir mit der Installation, was wir brauchen.
Schritt 1: Generieren Sie eine package.json-Datei
Erstellen Sie ein Verzeichnis für Ihre App. Führen Sie dies in diesem Verzeichnis von Ihrem Terminal oder Ihrer Eingabeaufforderung aus:
1 |
npm init |
Dadurch wird der npm-Abhängigkeitsmanager initialisiert. Dies wird eine Reihe von Eingabeaufforderungen präsentieren, die wir schnell durchgehen werden.
- Geben Sie den Namen Ihrer App ohne Leerzeichen ein und drücken Sie die Eingabetaste für "name".
- Drücken Sie die Eingabetaste für die 'version'.
- Für "description" geben wir in diesem Tutorial "Using Passport with Sequelize and MySQL" als Beschreibung ein und drücken die Eingabetaste. Dies kann auch leer sein.
- Geben Sie für 'entry point (index.js)' server.js ein und drücken Sie die Eingabetaste.
- Drücken Sie für 'test command' die Eingabetaste.
- Für 'git repository' können Sie das Git-Repository eingeben, in dem sich Ihre App befindet, falls Sie eines haben, oder einfach die Eingabetaste drücken, um dieses Feld leer zu lassen.
- Drücken Sie für 'Keywords' die Eingabetaste.
- Drücken Sie für 'author' die Eingabetaste oder geben Sie Ihren Namen ein, bevor Sie dies tun.
- Drücken Sie für 'license' die Eingabetaste.
- Für '(Is this okay)' zeigt Ihnen dies, wie Ihre package.json aussehen wird. Geben Sie Ja ein und drücken Sie die Eingabetaste.
Schritt 2: Abhängigkeiten installieren
Die wichtigsten Abhängigkeiten für dieses Tutorial sind:
- Express
- Sequelize
- MySQL
- Passport
- Passport Local Strategy
- Body Parser
- Express Session
- Bcrypt Nodejs
- Express Handlebars für die Ansichten
Um sie zu installieren, führen Sie von Ihrem Terminal oder Ihrer Eingabeaufforderung die folgenden Schritte nacheinander aus.
1 |
npm install express --save |
2 |
|
3 |
npm install sequelize --save |
4 |
|
5 |
npm install mysql --save |
6 |
|
7 |
npm install passport --save |
8 |
|
9 |
npm install passport-local --save |
10 |
|
11 |
npm install body-parser --save |
12 |
|
13 |
npm install express-session --save |
14 |
|
15 |
npm install bcrypt-nodejs --save |
16 |
|
17 |
npm install express-handlebars --save |
Wenn Sie Git für dieses Projekt verwenden:
Erstellen Sie in Ihrem Projektordner eine .gitignore-Datei.
Fügen Sie diese Zeile der .gitignore-Datei hinzu.
node_modules
Schritt 3: Einrichten der App
Nun erstellen wir eine Serverdatei. Dies ist die Hauptdatei, die aufgerufen wird, wenn Sie Folgendes eingeben:
1 |
npm start |
Dadurch wird die App ausgeführt. Sie können die App auch ausführen, indem Sie node server.js eingeben.
1 |
node server.js |
Dann erstellen wir in unserem Projektordner eine neue Datei und nennen diese Datei server.js.
In die Datei server.js fügen wir Folgendes ein:
1 |
var express = require('express'); |
2 |
var app = express(); |
3 |
|
4 |
|
5 |
app.get('/', function(req, res) { |
6 |
|
7 |
res.send('Welcome to Passport with Sequelize'); |
8 |
|
9 |
});
|
10 |
|
11 |
|
12 |
app.listen(5000, function(err) { |
13 |
|
14 |
if (!err) |
15 |
console.log("Site is live"); |
16 |
else console.log(err) |
17 |
|
18 |
});
|
Die erste Zeile weist das Express-Modul einer Variablen express zu. Wir initialisieren dann express und nennen es eine Variable: app.
Dann lassen wir die App auf Port 5000 lauschen. Sie können eine beliebige freie Portnummer auf Ihrem Computer wählen.
Als nächstes rufen wir die Express-Routing-Funktion app.get()
auf, um mit "Welcome to Passport with Sequelize" zu antworten, wenn eine GET-Anfrage an "/" gestellt wird.
Um auf Ihrem Computer zu testen, führen Sie dies in Ihrem Projektordner aus:
1 |
node server.js |
Wenn Sie beim Besuch von http://localhost:5000/ den Text "Welcome to Passport with Sequelize" sehen, dann herzlichen Glückwunsch! Überprüfen Sie andernfalls, ob Sie alles genau so gemacht haben, wie es oben beschrieben wurde.
Als nächstes importieren wir einige Module, die wir benötigen, wie Passport, Express-Session und Body-Parser.
Nach var app = express()
fügen wir die folgenden Zeilen hinzu:
1 |
var passport = require('passport') |
2 |
var session = require('express-session') |
3 |
var bodyParser = require('body-parser') |
In den ersten beiden Zeilen importieren wir das Passport-Modul und die Express-Session, die wir beide für die Authentifizierung benötigen.
Dann importieren wir das Body-Parser-Modul. Dadurch wird der gesamte Textteil einer eingehenden Anforderung extrahiert und in einem Format bereitgestellt, mit dem die Arbeit einfacher ist. In diesem Fall verwenden wir das JSON-Format.
Damit unsere App den Body-Parser verwenden kann, fügen wir diese Zeilen einige Leerzeichen unter den Importzeilen hinzu:
1 |
//For BodyParser
|
2 |
app.use(bodyParser.urlencoded({ extended: true })); |
3 |
app.use(bodyParser.json()); |
Als nächstes initialisieren wir Passport und die Express- und Passport-Sitzung und fügen beide als Middleware hinzu. Dazu fügen wir diese Zeilen einige Leerzeichen nach der bodyParser-Importzeile hinzu.
1 |
// For Passport
|
2 |
|
3 |
app.use(session({ secret: 'keyboard cat',resave: true, saveUninitialized:true})); // session secret |
4 |
|
5 |
app.use(passport.initialize()); |
6 |
|
7 |
app.use(passport.session()); // persistent login sessions |
Wir werden jetzt mit der eigentlichen Authentifizierung beginnen.
Wir machen das in vier Schritten:
- Sequelize mit MySQL einrichten.
- Erstellen Sie das Benutzermodell.
- Ansichten einrichten.
- Schreiben Sie eine Passstrategie.
1. Sequelize mit MySQL einrichten
Zuerst erstellen wir eine Datenbank in MySQL. Geben Sie ihm Ihren bevorzugten Namen. Lassen Sie uns für dieses Tutorial eine Datenbank mit dem Namen sequelize_passport
in MySQL erstellen.
Dann richten wir die Konfiguration ein, um DB-Details zu verarbeiten.
Lassen Sie uns zunächst das dot-env-Modul importieren, um Umgebungsvariablen zu verarbeiten.
Führen Sie dies in Ihrem Stammprojektordner aus:
1 |
npm install --save dotenv |
Dann importieren wir es in die Hauptserverdatei server.js, direkt unter den anderen Importen.
1 |
var env = require('dotenv').load(); |
Als nächstes erstellen wir eine Datei in unserem Projektordner und nennen sie .env.
Dieser nächste Schritt ist optional, wenn Sie Git nicht verwenden:
Wir fügen die .env-Datei zu Ihrer .gitignore-Datei hinzu.
Ihre .gitignore-Datei sollte so aussehen:
1 |
node_modules |
2 |
.env |
Danach fügen wir unsere Umgebung der .env-Datei hinzu, indem wir diese Zeile hinzufügen:
NODE_ENV='development'
Dann erstellen wir eine config.json-Datei, die von Sequelize verwendet wird, um verschiedene Umgebungen zu verwalten.
Als erstes erstellen Sie einen Ordner namens config
in unserem Projektordner. In diesem Ordner erstellen wir eine config.json-Datei. Diese Datei sollte ignoriert werden, wenn Sie auf ein Repository pushen. Fügen Sie dazu Ihrer .gitignore-Datei den folgenden Code hinzu:
config/config.json
Dann fügen wir den folgenden Code in unsere Datei config.json ein.
1 |
{ |
2 |
|
3 |
"development": { |
4 |
|
5 |
"username": "root", |
6 |
|
7 |
"password": null, |
8 |
|
9 |
"database": "sequelize_passport", |
10 |
|
11 |
"host": "127.0.0.1", |
12 |
|
13 |
"dialect": "mysql" |
14 |
|
15 |
}, |
16 |
|
17 |
"test": { |
18 |
|
19 |
"username": "", |
20 |
|
21 |
"password": null, |
22 |
|
23 |
"database": "", |
24 |
|
25 |
"host": "", |
26 |
|
27 |
"dialect": "mysql" |
28 |
|
29 |
}, |
30 |
|
31 |
"production": { |
32 |
|
33 |
"username": "", |
34 |
|
35 |
"password": null, |
36 |
|
37 |
"database": "", |
38 |
|
39 |
"host": "127.0.0.1", |
40 |
|
41 |
"dialect": "mysql" |
42 |
|
43 |
} |
44 |
|
45 |
} |
Denken Sie daran, die Werte im obigen Entwicklungsblock durch Ihre Datenbankauthentifizierungsdetails zu ersetzen.
Als nächstes installieren wir Sequelize mit npm. Führen Sie dazu den folgenden Befehl im Stammordner des Projekts aus:
1 |
npm install --save sequelize |
Jetzt ist es an der Zeit, den models-Ordner zu erstellen.
Zuerst erstellen wir ein Verzeichnis namens app
in unserem Projektordner.
Innerhalb des app-Ordners erstellen wir einen neuen Ordner namens models und erstellen eine neue Datei namens index.js im Ordner models.
In die Datei index.js fügen wir den folgenden Code ein.
1 |
"use strict"; |
2 |
|
3 |
var fs = require("fs"); |
4 |
var path = require("path"); |
5 |
var Sequelize = require("sequelize"); |
6 |
var env = process.env.NODE_ENV || "development"; |
7 |
var config = require(path.join(__dirname, '..', 'config', 'config.json'))[env]; |
8 |
var sequelize = new Sequelize(config.database, config.username, config.password, config); |
9 |
var db = {}; |
10 |
|
11 |
|
12 |
fs
|
13 |
.readdirSync(__dirname) |
14 |
.filter(function(file) { |
15 |
return (file.indexOf(".") !== 0) && (file !== "index.js"); |
16 |
})
|
17 |
.forEach(function(file) { |
18 |
var model = sequelize.import(path.join(__dirname, file)); |
19 |
db[model.name] = model; |
20 |
});
|
21 |
|
22 |
Object.keys(db).forEach(function(modelName) { |
23 |
if ("associate" in db[modelName]) { |
24 |
db[modelName].associate(db); |
25 |
}
|
26 |
});
|
27 |
|
28 |
|
29 |
db.sequelize = sequelize; |
30 |
db.Sequelize = Sequelize; |
31 |
|
32 |
module.exports = db; |
Diese Datei wird verwendet, um alle Modelle, die wir im models-Ordner platzieren, zu importieren und zu exportieren.
Um zu testen, ob alles in Ordnung ist, fügen wir dies in unsere Datei server.js ein.
1 |
//Models
|
2 |
var models = require("./app/models"); |
3 |
|
4 |
//Sync Database
|
5 |
models.sequelize.sync().then(function() { |
6 |
|
7 |
console.log('Nice! Database looks fine') |
8 |
|
9 |
}).catch(function(err) { |
10 |
|
11 |
console.log(err, "Something went wrong with the Database Update!") |
12 |
|
13 |
});
|
Hier importieren wir die Modelle und rufen dann die Sequelize-Synchronisierungsfunktion auf.
Führen Sie dies aus, um zu sehen, ob alles in Ordnung ist:
1 |
node server.js |
Wenn Sie die Meldung "Site is live Nice! Database sieht in Ordnung" erhalten, haben Sie Sequelize erfolgreich eingerichtet.
Wenn nicht, gehen Sie bitte die obigen Schritte sorgfältig durch und versuchen Sie, das Problem mit Hilfe zu beheben.
2. Erstellen Sie das Benutzermodell
Als nächstes erstellen wir das Benutzermodell, das im Grunde die Benutzertabelle ist. Diese enthält grundlegende Benutzerinformationen.
In unserem models-Ordner erstellen wir eine Datei und nennen sie user.js. Der vollständige Pfad für diese Datei sollte app/models/user.js lauten.
Öffnen Sie die Datei user.js und fügen Sie den folgenden Code hinzu:
1 |
module.exports = function(sequelize, Sequelize) { |
2 |
|
3 |
var User = sequelize.define('user', { |
4 |
|
5 |
id: { |
6 |
autoIncrement: true, |
7 |
primaryKey: true, |
8 |
type: Sequelize.INTEGER |
9 |
},
|
10 |
|
11 |
firstname: { |
12 |
type: Sequelize.STRING, |
13 |
notEmpty: true |
14 |
},
|
15 |
|
16 |
lastname: { |
17 |
type: Sequelize.STRING, |
18 |
notEmpty: true |
19 |
},
|
20 |
|
21 |
username: { |
22 |
type: Sequelize.TEXT |
23 |
},
|
24 |
|
25 |
about: { |
26 |
type: Sequelize.TEXT |
27 |
},
|
28 |
|
29 |
email: { |
30 |
type: Sequelize.STRING, |
31 |
validate: { |
32 |
isEmail: true |
33 |
}
|
34 |
},
|
35 |
|
36 |
password: { |
37 |
type: Sequelize.STRING, |
38 |
allowNull: false |
39 |
},
|
40 |
|
41 |
last_login: { |
42 |
type: Sequelize.DATE |
43 |
},
|
44 |
|
45 |
status: { |
46 |
type: Sequelize.ENUM('active', 'inactive'), |
47 |
defaultValue: 'active' |
48 |
}
|
49 |
|
50 |
|
51 |
});
|
52 |
|
53 |
return User; |
54 |
|
55 |
}
|
Führen Sie nun aus:
1 |
node server.js |
Sie sollten das bekannte "Site is live. Nice! Database sieht in Ordnung" sehen. Botschaft. Dies bedeutet, dass unsere Sequelize-Modelle erfolgreich synchronisiert wurden, und wenn Sie Ihre Datenbank überprüfen, sollten Sie eine Benutzertabelle mit den angegebenen Spalten sehen.
3: Ansichten einrichten
Zuerst erstellen wir die Ansicht für die Anmeldung und verbinden sie.
Als erstes müssen Sie das Express-Lenkermodul importieren, das wir in diesem Tutorial für Ansichten verwenden.
Fügen Sie diese Zeile der Hauptstartdatei server.js hinzu.
var exphbs = require('express-handlebars')
Ihr Importblock sollte jetzt so aussehen.
1 |
var express = require('express') |
2 |
var app = express() |
3 |
var passport = require('passport') |
4 |
var session = require('express-session') |
5 |
var bodyParser = require('body-parser') |
6 |
var env = require('dotenv').load() |
7 |
var exphbs = require('express-handlebars') |
Als nächstes fügen wir die folgenden Zeilen in unsere Datei server.js ein.
1 |
//For Handlebars
|
2 |
app.set('views', './app/views') |
3 |
app.engine('hbs', exphbs({ |
4 |
extname: '.hbs' |
5 |
}));
|
6 |
app.set('view engine', '.hbs'); |
Jetzt erstellen wir in unserem App-Ordner drei Ordner mit den Namen Ansichten, Controller und Routen.
Im Ordner "views" erstellen wir eine Datei namens signup.hbs und fügen den folgenden Code darin ein.
1 |
<!DOCTYPE html>
|
2 |
<html>
|
3 |
|
4 |
<head>
|
5 |
<title></title>
|
6 |
</head>
|
7 |
|
8 |
<body>
|
9 |
<form id="signup" name="signup" method="post" action="/signup"> |
10 |
<label for="email">Email Address</label> |
11 |
<input class="text" name="email" type="email" /> |
12 |
<label for="firstname">Firstname</label> |
13 |
<input name="firstname" type="text" /> |
14 |
<label for="lastname">Lastname</label> |
15 |
<input name="lastname" type="text" /> |
16 |
<label for="password">Password</label> |
17 |
<input name="password" type="password" /> |
18 |
<input class="btn" type="submit" value="Sign Up" /> |
19 |
</form>
|
20 |
|
21 |
</body>
|
22 |
|
23 |
</html>
|
Dann erstellen wir in unserem controllers-Ordner eine neue Datei und nennen sie authcontroller.js.
In diese Datei fügen wir den folgenden Controller für die Anmelderoute ein, die wir gleich erstellen werden.
1 |
var exports = module.exports = {} |
2 |
|
3 |
exports.signup = function(req, res) { |
4 |
|
5 |
res.render('signup'); |
6 |
|
7 |
}
|
Als nächstes erstellen wir eine Route für die Anmeldung. Im Routenordner erstellen wir eine neue Datei namens auth.js und importieren dann in dieser Datei den Auth-Controller und definieren die Anmelderoute.
1 |
var authController = require('../controllers/authcontroller.js'); |
2 |
|
3 |
module.exports = function(app) { |
4 |
|
5 |
app.get('/signup', authController.signup); |
6 |
|
7 |
}
|
Jetzt importieren wir diese Route in unsere server.js und übergeben app als Argument.
Fügen Sie im Server nach dem Import der Modelle die folgenden Zeilen hinzu:
1 |
//Routes
|
2 |
var authRoute = require('./app/routes/auth.js')(app); |
Führen Sie dies aus:
1 |
node server.js |
Besuchen Sie jetzt http://localhost:5000/signup und Sie sehen das Anmeldeformular.
Wiederholen Sie die Schritte für das Anmeldeformular. Wie zuvor erstellen wir eine Datei namens signin.hbs in unserem Ansichtenordner und fügen den folgenden HTML-Code darin ein:
1 |
<!DOCTYPE html>
|
2 |
<html>
|
3 |
|
4 |
<head>
|
5 |
<title></title>
|
6 |
</head>
|
7 |
|
8 |
<body>
|
9 |
<form id="signin" name="signin" method="post" action="signin"> |
10 |
<label for="email">Email Address</label> |
11 |
<input class="text" name="email" type="text" /> |
12 |
<label for="password">Password</label> |
13 |
<input name="password" type="password" /> |
14 |
<input class="btn" type="submit" value="Sign In" /> |
15 |
</form>
|
16 |
|
17 |
</body>
|
18 |
|
19 |
</html>
|
Fügen Sie dann einen Controller für die Anmeldung in app/controllers/authcontroller.js hinzu.
1 |
exports.signin = function(req, res) { |
2 |
|
3 |
res.render('signin'); |
4 |
|
5 |
}
|
Dann fügen wir in app/routes/auth.js eine Route für die Anmeldung wie folgt hinzu:
app.get('/signin', authController.signin);
Wenn Sie jetzt laufen:
1 |
node server.js |
und besuchen Sie http://localhost:5000/signin/, Sie sollten das Anmeldeformular sehen.
Der letzte und wichtigste Schritt ist das Schreiben unserer Passstrategien.
4. Schreiben Sie eine Pass-Strategie
In app/config erstellen wir einen neuen Ordner namens passport.
Dann erstellen wir in unserem neuen Ordner app/config/passport eine neue Datei und nennen sie passport.js. Diese Datei enthält unsere Passstrategien.
In passport.js verwenden wir das Benutzermodell und den Passport.
Zuerst importieren wir bcrypt, das wir zum Sichern von Passwörtern benötigen.
var bCrypt = require('bcrypt-nodejs');
Dann fügen wir einen module.exports-Block wie folgt hinzu:
1 |
module.exports = function(passport, user) { |
2 |
|
3 |
}
|
In diesem Block initialisieren wir die Passport-Local-Strategie und das Benutzermodell, das als Argument übergeben wird. So machen wir das:
1 |
module.exports = function(passport, user) { |
2 |
|
3 |
var User = user; |
4 |
var LocalStrategy = require('passport-local').Strategy; |
5 |
|
6 |
}
|
Dann definieren wir unsere benutzerdefinierte Strategie mit unserer Instanz der LocalStrategy wie folgt:
1 |
passport.use('local-signup', new LocalStrategy( |
2 |
|
3 |
{
|
4 |
usernameField: 'email', |
5 |
passwordField: 'password', |
6 |
passReqToCallback: true // allows us to pass back the entire request to the callback |
7 |
|
8 |
},
|
9 |
|
10 |
));
|
Jetzt haben wir deklariert, welche Anfragefelder (req) unser usernameField und passwordField (Passport-Variablen) sind.
Die letzte Variable passReqToCallback ermöglicht es uns, die gesamte Anfrage an den Callback zu übergeben, was besonders für die Anmeldung nützlich ist.
Nach dem letzten Komma fügen wir diese Callback-Funktion hinzu.
1 |
function(req, email, password, done) { |
2 |
|
3 |
}
|
In dieser Funktion übernehmen wir die Speicherung von Benutzerdaten.
Zuerst fügen wir unsere Funktion zum Generieren von Hash-Passwörtern in die Callback-Funktion ein.
1 |
var generateHash = function(password) { |
2 |
|
3 |
return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null); |
4 |
|
5 |
};
|
Dann überprüfen wir mit dem Sequelize-Benutzermodell, das wir zuvor als User initialisiert haben, ob der Benutzer bereits existiert, und fügen ihn gegebenenfalls hinzu.
1 |
User.findOne({ |
2 |
where: { |
3 |
email: email |
4 |
}
|
5 |
}).then(function(user) { |
6 |
|
7 |
if (user) |
8 |
|
9 |
{
|
10 |
|
11 |
return done(null, false, { |
12 |
message: 'That email is already taken' |
13 |
});
|
14 |
|
15 |
} else |
16 |
|
17 |
{
|
18 |
|
19 |
var userPassword = generateHash(password); |
20 |
|
21 |
var data = |
22 |
|
23 |
{
|
24 |
email: email, |
25 |
|
26 |
password: userPassword, |
27 |
|
28 |
firstname: req.body.firstname, |
29 |
|
30 |
lastname: req.body.lastname |
31 |
|
32 |
};
|
33 |
|
34 |
|
35 |
User.create(data).then(function(newUser, created) { |
36 |
|
37 |
if (!newUser) { |
38 |
|
39 |
return done(null, false); |
40 |
|
41 |
}
|
42 |
|
43 |
if (newUser) { |
44 |
|
45 |
return done(null, newUser); |
46 |
|
47 |
}
|
48 |
|
49 |
});
|
50 |
|
51 |
}
|
52 |
|
53 |
});
|
User.create()
ist eine Sequelize-Methode zum Hinzufügen neuer Einträge zur Datenbank. Beachten Sie, dass die Werte im data-Objekt aus dem req.body-Objekt stammen, das die Eingabe aus unserem Anmeldeformular enthält.
Ihre passport.js sollte so aussehen:
1 |
//load bcrypt
|
2 |
var bCrypt = require('bcrypt-nodejs'); |
3 |
|
4 |
|
5 |
module.exports = function(passport, user) { |
6 |
|
7 |
|
8 |
var User = user; |
9 |
|
10 |
var LocalStrategy = require('passport-local').Strategy; |
11 |
|
12 |
|
13 |
passport.use('local-signup', new LocalStrategy( |
14 |
|
15 |
{
|
16 |
|
17 |
usernameField: 'email', |
18 |
|
19 |
passwordField: 'password', |
20 |
|
21 |
passReqToCallback: true // allows us to pass back the entire request to the callback |
22 |
|
23 |
},
|
24 |
|
25 |
|
26 |
|
27 |
function(req, email, password, done) { |
28 |
|
29 |
var generateHash = function(password) { |
30 |
|
31 |
return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null); |
32 |
|
33 |
};
|
34 |
|
35 |
|
36 |
|
37 |
User.findOne({ |
38 |
where: { |
39 |
email: email |
40 |
}
|
41 |
}).then(function(user) { |
42 |
|
43 |
if (user) |
44 |
|
45 |
{
|
46 |
|
47 |
return done(null, false, { |
48 |
message: 'That email is already taken' |
49 |
});
|
50 |
|
51 |
} else |
52 |
|
53 |
{
|
54 |
|
55 |
var userPassword = generateHash(password); |
56 |
|
57 |
var data = |
58 |
|
59 |
{
|
60 |
email: email, |
61 |
|
62 |
password: userPassword, |
63 |
|
64 |
firstname: req.body.firstname, |
65 |
|
66 |
lastname: req.body.lastname |
67 |
|
68 |
};
|
69 |
|
70 |
User.create(data).then(function(newUser, created) { |
71 |
|
72 |
if (!newUser) { |
73 |
|
74 |
return done(null, false); |
75 |
|
76 |
}
|
77 |
|
78 |
if (newUser) { |
79 |
|
80 |
return done(null, newUser); |
81 |
|
82 |
}
|
83 |
|
84 |
});
|
85 |
|
86 |
}
|
87 |
|
88 |
});
|
89 |
|
90 |
}
|
91 |
|
92 |
));
|
93 |
|
94 |
}
|
Jetzt importieren wir die Strategie in server.js.
Dazu fügen wir diese Zeilen unterhalb des Routenimports in server.js hinzu.
1 |
//load passport strategies
|
2 |
require('./app/config/passport/passport.js')(passport, models.user); |
Ihre server.js sollte zu diesem Zeitpunkt so aussehen:
1 |
var express = require('express') |
2 |
var app = express() |
3 |
var passport = require('passport') |
4 |
var session = require('express-session') |
5 |
var bodyParser = require('body-parser') |
6 |
var env = require('dotenv').load() |
7 |
var exphbs = require('express-handlebars') |
8 |
|
9 |
|
10 |
//For BodyParser
|
11 |
app.use(bodyParser.urlencoded({ |
12 |
extended: true |
13 |
}));
|
14 |
app.use(bodyParser.json()); |
15 |
|
16 |
|
17 |
// For Passport
|
18 |
app.use(session({ |
19 |
secret: 'keyboard cat', |
20 |
resave: true, |
21 |
saveUninitialized: true |
22 |
})); // session secret |
23 |
app.use(passport.initialize()); |
24 |
app.use(passport.session()); // persistent login sessions |
25 |
|
26 |
|
27 |
//For Handlebars
|
28 |
app.set('views', './app/views') |
29 |
app.engine('hbs', exphbs({ |
30 |
extname: '.hbs' |
31 |
}));
|
32 |
app.set('view engine', '.hbs'); |
33 |
|
34 |
|
35 |
|
36 |
app.get('/', function(req, res) { |
37 |
|
38 |
res.send('Welcome to Passport with Sequelize'); |
39 |
|
40 |
});
|
41 |
|
42 |
//Models
|
43 |
var models = require("./app/models"); |
44 |
|
45 |
//Routes
|
46 |
|
47 |
var authRoute = require('./app/routes/auth.js')(app); |
48 |
|
49 |
|
50 |
//load passport strategies
|
51 |
|
52 |
require('./app/config/passport/passport.js')(passport, models.user); |
53 |
|
54 |
|
55 |
//Sync Database
|
56 |
|
57 |
models.sequelize.sync().then(function() { |
58 |
|
59 |
console.log('Nice! Database looks fine') |
60 |
|
61 |
|
62 |
}).catch(function(err) { |
63 |
|
64 |
console.log(err, "Something went wrong with the Database Update!") |
65 |
|
66 |
});
|
67 |
|
68 |
|
69 |
app.listen(5000, function(err) { |
70 |
|
71 |
if (!err) |
72 |
|
73 |
console.log("Site is live"); |
74 |
|
75 |
else console.log(err) |
76 |
|
77 |
});
|
Jetzt werden wir die Strategie tatsächlich auf unsere /signup-Route anwenden.
So machen wir das:
Zuerst gehen wir zu app/routes/auth.js und fügen eine Route zum Posten hinzu, um sich wie folgt anzumelden.
1 |
app.post('/signup', passport.authenticate('local-signup', { |
2 |
successRedirect: '/dashboard', |
3 |
|
4 |
failureRedirect: '/signup' |
5 |
}
|
6 |
|
7 |
));
|
Da wir einen Reisepass benötigen, müssen wir ihn an diese Methode übergeben. Wir können den Passport in dieses Skript importieren oder von server.js übergeben. Machen wir letzteres.
Ändern Sie die exportierte Funktion in dieser Datei app/routes/auth.js so, dass sie Passport als Parameter hat. Der Code in app/routes/auth.js sollte nach Ihrer Änderung so aussehen.
1 |
var authController = require('../controllers/authcontroller.js'); |
2 |
|
3 |
|
4 |
module.exports = function(app, passport) { |
5 |
|
6 |
app.get('/signup', authController.signup); |
7 |
|
8 |
|
9 |
app.get('/signin', authController.signin); |
10 |
|
11 |
|
12 |
app.post('/signup', passport.authenticate('local-signup', { |
13 |
successRedirect: '/dashboard', |
14 |
|
15 |
failureRedirect: '/signup' |
16 |
}
|
17 |
|
18 |
));
|
19 |
|
20 |
|
21 |
|
22 |
}
|
Dann ändern wir in server.js den Routenimport und fügen den Passport wie folgt als Argument hinzu:
var authRoute = require('./app/routes/auth.js')(app,passport);
Gehen Sie nun zur Anmelde-URL http://localhost:5000/signup/ und versuchen Sie, sich anzumelden.
Wenn Sie versuchen, sich anzumelden, erhalten Sie eine Fehlermeldung "Fehler beim Serialisieren des Benutzers in die Sitzung". Dies liegt daran, dass Passport eine Benutzer-ID in der Sitzung speichern muss und diese verwendet, um das Abrufen der Benutzerdetails bei Bedarf zu verwalten.
Um dies zu lösen, implementieren wir die Serialisierungs- und Deserialisierungsfunktionen von Passport in unserer Datei app/config/passport/passport.js.
Zuerst fügen wir die Serialisierungsfunktion hinzu. In dieser Funktion speichern wir die user id in der Sitzung.
Dazu fügen wir die folgenden Zeilen unterhalb der Initialisierung der lokalen Strategie ein.
1 |
//serialize
|
2 |
passport.serializeUser(function(user, done) { |
3 |
|
4 |
done(null, user.id); |
5 |
|
6 |
});
|
Als nächstes implementieren wir die Deserialize-Funktion. Fügen Sie die Funktion direkt unter der Serialisierungsfunktion hinzu.
1 |
// deserialize user
|
2 |
passport.deserializeUser(function(id, done) { |
3 |
|
4 |
User.findById(id).then(function(user) { |
5 |
|
6 |
if (user) { |
7 |
|
8 |
done(null, user.get()); |
9 |
|
10 |
} else { |
11 |
|
12 |
done(user.errors, null); |
13 |
|
14 |
}
|
15 |
|
16 |
});
|
17 |
|
18 |
});
|
In der obigen Deserialize-Funktion verwenden wir das Sequelize findById
-Versprechen, um den Benutzer abzurufen, und bei Erfolg wird eine Instanz des Sequelize-Modells zurückgegeben. Um das User-Objekt von dieser Instanz abzurufen, verwenden wir die Sequelize-Getter-Funktion wie folgt: user.get()
.
Jetzt noch einmal ausführen:
1 |
node server.js |
Und versuchen Sie sich anzumelden. Hurra, wenn Sie das "Cannot GET /dashboard" bekommen haben! Dies bedeutet, dass unsere Authentifizierung erfolgreich war. Denken Sie daran, dass wir in unserer Methode Passport.authenticate in routes/auth.js auf /dashboard umgeleitet haben.
Lassen Sie uns nun fortfahren und diese Route hinzufügen. Fügen Sie dann eine Middleware hinzu, um sicherzustellen, dass die Seite nur aufgerufen werden kann, wenn ein Benutzer bei der Sitzung angemeldet ist.
In unserem app/views-Ordner erstellen wir eine neue Datei namens dashboard.hbs und fügen den folgenden HTML-Code hinzu.
1 |
<!DOCTYPE html>
|
2 |
<html>
|
3 |
|
4 |
<head>
|
5 |
<title>Passport with Sequelize</title> |
6 |
</head>
|
7 |
|
8 |
<body>
|
9 |
<h2>Dashboard</h2> |
10 |
<h5>Hurray! you are logged in.</h5> |
11 |
|
12 |
</body>
|
13 |
|
14 |
</html>
|
In routes/auth.js fügen wir diese Zeile innerhalb des module.exports-Blocks hinzu:
app.get('/dashboard',authController.dashboard);
Als nächstes gehen wir zu app/controllers/authController.js und fügen den Dashboard-Controller hinzu.
1 |
exports.dashboard = function(req, res) { |
2 |
|
3 |
res.render('dashboard'); |
4 |
|
5 |
}
|
Ihre AuthController.js sollte so aussehen:
1 |
var exports = module.exports = {} |
2 |
|
3 |
|
4 |
exports.signup = function(req, res) { |
5 |
|
6 |
res.render('signup'); |
7 |
|
8 |
}
|
9 |
|
10 |
exports.signin = function(req, res) { |
11 |
|
12 |
res.render('signin'); |
13 |
|
14 |
}
|
15 |
|
16 |
|
17 |
exports.dashboard = function(req, res) { |
18 |
|
19 |
res.render('dashboard'); |
20 |
|
21 |
}
|
Führen Sie nun die App erneut aus und versuchen Sie, sich mit einer anderen E-Mail-Adresse als der zuvor verwendeten anzumelden. Sie werden entsprechend zur /dashboard-Route weitergeleitet.
Aber /dashboard ist keine geschützte Route, das heißt, auch wenn ein Benutzer nicht angemeldet ist, kann er ihn sehen. Wir wollen dies nicht, also fügen wir eine /logout-Route hinzu, um den Benutzer abzumelden, und schützen dann die Route und testen, was wir getan haben.
Lass uns das machen:
In routes/auth.js fügen wir diese Zeile hinzu:
app.get('/logout',authController.logout);
Dann fügen wir den Controller in app/controllers/authController.js hinzu.
1 |
exports.logout = function(req, res) { |
2 |
|
3 |
req.session.destroy(function(err) { |
4 |
|
5 |
res.redirect('/'); |
6 |
|
7 |
});
|
8 |
|
9 |
}
|
Führen Sie nun die App erneut aus und melden Sie sich mit einer anderen E-Mail-Adresse an.
Rufen Sie danach http://localhost:5000/logout auf, um den Benutzer abzumelden. Besuchen Sie jetzt http://localhost:5000/dashboard.
Sie werden feststellen, dass es gut zugänglich ist. Fügen wir eine benutzerdefinierte Middleware hinzu, um diese Route zu schützen.
Dazu öffnen wir app/routes/auth.js und fügen diese Funktion im module.exports-Block unter allen anderen Codezeilen hinzu.
1 |
function isLoggedIn(req, res, next) { |
2 |
|
3 |
if (req.isAuthenticated()) |
4 |
|
5 |
return next(); |
6 |
|
7 |
res.redirect('/signin'); |
8 |
|
9 |
}
|
Dann ändern wir den Routen-Handler des Dashboards so, dass er wie folgt aussieht:
app.get('/dashboard',isLoggedIn, authController.dashboard);
Wenn Sie nun die App erneut ausführen und versuchen, die Dashboard-Seite zu besuchen und nicht angemeldet sind, sollten Sie zur Anmeldeseite weitergeleitet werden.
Wütend! Es ist Zeit, den letzten Teil zu implementieren: die Anmeldung.
Zuerst fügen wir eine neue lokale Strategie für die Anmeldung in app/config/passport/passport.js hinzu.
1 |
//LOCAL SIGNIN
|
2 |
passport.use('local-signin', new LocalStrategy( |
3 |
|
4 |
{
|
5 |
|
6 |
// by default, local strategy uses username and password, we will override with email
|
7 |
|
8 |
usernameField: 'email', |
9 |
|
10 |
passwordField: 'password', |
11 |
|
12 |
passReqToCallback: true // allows us to pass back the entire request to the callback |
13 |
|
14 |
},
|
15 |
|
16 |
|
17 |
function(req, email, password, done) { |
18 |
|
19 |
var User = user; |
20 |
|
21 |
var isValidPassword = function(userpass, password) { |
22 |
|
23 |
return bCrypt.compareSync(password, userpass); |
24 |
|
25 |
}
|
26 |
|
27 |
User.findOne({ |
28 |
where: { |
29 |
email: email |
30 |
}
|
31 |
}).then(function(user) { |
32 |
|
33 |
if (!user) { |
34 |
|
35 |
return done(null, false, { |
36 |
message: 'Email does not exist' |
37 |
});
|
38 |
|
39 |
}
|
40 |
|
41 |
if (!isValidPassword(user.password, password)) { |
42 |
|
43 |
return done(null, false, { |
44 |
message: 'Incorrect password.' |
45 |
});
|
46 |
|
47 |
}
|
48 |
|
49 |
|
50 |
var userinfo = user.get(); |
51 |
return done(null, userinfo); |
52 |
|
53 |
|
54 |
}).catch(function(err) { |
55 |
|
56 |
console.log("Error:", err); |
57 |
|
58 |
return done(null, false, { |
59 |
message: 'Something went wrong with your Signin' |
60 |
});
|
61 |
|
62 |
});
|
63 |
|
64 |
|
65 |
}
|
66 |
|
67 |
));
|
Bei dieser Strategie vergleicht die Funktion isValidPassword
das eingegebene Passwort mit der Vergleichsmethode bCrypt, da wir unser Passwort bei bcrypt gespeichert haben.
Wenn die Angaben korrekt sind, wird unser Benutzer angemeldet.
Gehen Sie nun zu routes/auth.js und fügen Sie die Route zum Posten zu /signin hinzu.
1 |
app.post('/signin', passport.authenticate('local-signin', { |
2 |
successRedirect: '/dashboard', |
3 |
|
4 |
failureRedirect: '/signin' |
5 |
}
|
6 |
|
7 |
));
|
Ihre routes/auth.js sollten so aussehen, wenn Sie fertig sind.
1 |
var authController = require('../controllers/authcontroller.js'); |
2 |
|
3 |
|
4 |
module.exports = function(app, passport) { |
5 |
|
6 |
|
7 |
app.get('/signup', authController.signup); |
8 |
|
9 |
|
10 |
app.get('/signin', authController.signin); |
11 |
|
12 |
|
13 |
app.post('/signup', passport.authenticate('local-signup', { |
14 |
successRedirect: '/dashboard', |
15 |
|
16 |
failureRedirect: '/signup' |
17 |
}
|
18 |
|
19 |
));
|
20 |
|
21 |
|
22 |
app.get('/dashboard', isLoggedIn, authController.dashboard); |
23 |
|
24 |
|
25 |
|
26 |
app.get('/logout', authController.logout); |
27 |
|
28 |
|
29 |
app.post('/signin', passport.authenticate('local-signin', { |
30 |
successRedirect: '/dashboard', |
31 |
|
32 |
failureRedirect: '/signin' |
33 |
}
|
34 |
|
35 |
));
|
36 |
|
37 |
|
38 |
function isLoggedIn(req, res, next) { |
39 |
|
40 |
if (req.isAuthenticated()) |
41 |
|
42 |
return next(); |
43 |
|
44 |
res.redirect('/signin'); |
45 |
|
46 |
}
|
47 |
|
48 |
}
|
Führen Sie nun die App aus und versuchen Sie, sich anzumelden. Sie sollten sich mit allen Details anmelden können, die Sie bei der Anmeldung verwendet haben, und Sie werden zu http://localhost:5000/dashboard/ weitergeleitet.
Herzlichen Glückwunsch, wenn Sie es bis zum Ende dieses Tutorials geschafft haben! Wir haben Sequelize und Passport erfolgreich mit einer MySQL-Datenbank verwendet.
Den vollständigen Code für dieses Tutorial finden Sie auf GitHub.
Abschluss
Damit ist unser Tutorial zur Verwendung von Passport zur Authentifizierung von Benutzern mit Sequelize und MySQL abgeschlossen. Sequelize ist ein wirklich nützliches ORM für den Umgang mit MySQL bei der Verwendung von Node. Ich persönlich fand es sehr nützlich, und Sie sollten auf jeden Fall in Betracht ziehen, es in Ihrer nächsten Node-MySQL-App zu verwenden.