JWT – это json web token.
Он формируется путем кодирования данных при помощи секретного слова. Более подробно о нем написано: https://jwt.io/
Также будем использовать библиотеку passport: http://www.passportjs.org/
И так поехали. Структура проекта:
config
config.json
models
db.js
routes
index.js
app.js
Файл app.js:
const express = require('express');
const bodyParser = require('body-parser');
const router = require('./routes');
const app = express();
const passport = require('passport');
const passportJWT = require('passport-jwt');
const ExtractJWT = passportJWT.ExtractJwt;
const Strategy = passportJWT.Strategy;
const db = require('./models/db');
const config = require('./config/config');
const PORT = process.env.PORT || 3000
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
const params = {
secretOrKey: config.secret,
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken()
};
let strategy = new Strategy(params, function(payload, done){
db
.getUserId(payload.id)
.then((results)=>{
if (results.length == 0) {
return done(new Error('Юзер не найден'), null)
} else {
return done(null, {
id: results._id
})
}
})
.catch((err)=>{
return done(err);
})
})
passport.use(strategy);
app.use('/', router);
app.use(function(req, res, next){
const err = new Error('Ни хрена не найдено!');
err.status = 404;
next(err);
});
app.use(function(err, req, res, next){
res.status(err.status || 500);
res.json({
message: err.message,
error: err
})
})
const server = app.listen(PORT, function () {
console.log('Сервер пашет на порту: ' + server.address().port);
})
Что здесь нового:
Подключаем библиотеки passport и passport-jwt
const passport = require('passport');
const passportJWT = require('passport-jwt');
const ExtractJWT = passportJWT.ExtractJwt;
const Strategy = passportJWT.Strategy;
Далее указываем параметры:
const params = {
secretOrKey: config.secret,
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken()
};
secretOrKey – секретное слово берется из файла config.json:
{
"secret" : "очень секретное слово"
}
Далее описываем стратегию:
let strategy = new Strategy(params, function(payload, done){
db
.getUserId(payload.id)
.then((results)=>{
if (results.length == 0) {
return done(new Error('Юзер не найден'), null)
} else {
return done(null, {
id: results._id
})
}
})
.catch((err)=>{
return done(err);
})
})
Ищет пользователя по id в базе и возвращает id
Далее юзаем стратегию:
passport.use(strategy);
Файл db.js:
const MongoClient = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;
const url = "путь подключения к базе";
const baza = 'test1';
module.exports.getUser = function(email) {
return new Promise((resolve, reject)=>{
MongoClient
.connect(url, function(err, client){
if (err) {
reject(err);
}
client
.db(baza)
.collection('users')
.find({ "email": email})
.toArray(function(err, results){
if (err) {
reject(err)
}
client.close();
resolve(results);
})
})
})
}
module.exports.getUserId = function(userId) {
return new Promise((resolve, reject) => {
const id = new ObjectID(userId);
MongoClient
.connect(url, function(err, client) {
if (err) {
reject(err);
}
client
.db(baza)
.collection('users')
.find({ _id: id })
.toArray(function(err, results){
if (err) {
reject(err);
}
client.close();
resolve(results);
})
});
})
}
Файл routes/index.js:
const express = require('express');
const router = express.Router();
const db = require('../models/db');
const bcrypt = require('bcryptjs');
const jwt = require('jwt-simple');
const config = require('../config/config');
let passport = require('passport');
let auth = passport.authenticate('jwt', {
session: false
});
const isValidPassword = function(user, password) {
return bcrypt.compareSync(password, user.password);
}
router.get('/', (req, res)=>{
res.json({
message: 'Добро пожаловать!'
})
});
router.get('/secret', auth, (req, res)=>{
res.json({
message: 'Секретная страница!'
})
});
router.post('/login', (req, res, next)=>{
db
.getUser(req.body.email)
.then((results)=>{
if (isValidPassword(results[0], req.body.password)) {
let payload ={
id: results[0]._id
}
let token = jwt.encode(payload, config.secret);
res.json({token: token});
} else {
const err = new Error('Не верный логин или пароль!');
err.status = 400;
next(err);
}
})
.catch((err)=>{
next(err);
})
})
module.exports = router;
Что у нас здесь нового:
Подключаем библиотеку ‘jwt-simple’ – для формирования токена:
const jwt = require('jwt-simple');
Мидделвэр auth – теперь стал намного проще:
let auth = passport.authenticate('jwt', {
session: false
});
В Роуте login – теперь если с пользователем все ок, то токен формируется:
let payload ={
id: results[0]._id
}
let token = jwt.encode(payload, config.secret);
И также теперь при обращении на secret, нужно в заголовках в параметре ‘
Authorization’ – указывать Bearer, потом пробел, потом токен
Вот и все, вроде тоже не сложно!