Здравствуйте,
Вот я пишу свой первый блог 😇 о том, как нам подключить простое [NodeJS приложение] 😎(https://www.npmjs.com/package/express) к Postgres и использовать PassportJS для аутентификации и авторизации.
Итак, базовая настройка машины будет выглядеть следующим образом:
Node JS - v12 or above
Шаг 1:
Давайте создадим простой модуль npm с помощью npm init
в директории, в которой вы хотите создать свое приложение.
> npm init
Он задаст вам следующие вопросы для конфигурации
Вы можете нажать Enter для каждого вопроса или добавить свои собственные настройки, я использую настройки по умолчанию.
Шаг 2:
Теперь нам нужны зависимости, которые должны быть установлены для нашего приложения, чтобы использовать их во время компиляции кода:
Вот как выглядит мой package.json:
Вот команда, которую вы можете выполнить для установки зависимостей:
npm i --save bcrypt-nodejs cors express jsonwebtoken nodemon passport passport-jwt passport-local pg pg-hstore sequelize
Давайте поймаем все зависимости и их работу для нас:
-
bcrypt-nodejs
: Он поможет нам зашифровать и расшифровать пароль при создании нового пользователя. -
cors
: Для разрешения CROSS ORIGIN REQUESTS установите, если хотите или нужно. -
express
: Он создаст сервер, чтобы мы могли использовать его маршруты. -
jsonwebtoken
: Для создания JWT-токена для авторизации API. -
passport
: Для простой аутентификации пользователя. -
passport-jwt
: Для JWT-авторизации. -
passport-local
: Для LocalStrategy аутентификации входа в систему. -
pg pg-hstore sequelize
: Для доступа к БД Postgres
Шаг 3:
Давайте создадим простой сервер для запуска нашего проекта:
вот что у меня есть в моем файле index.js
:
// project/index.js
const express = require('express')
const db = require('./models')
var cors = require('cors')
const app = express()
const port = 3000
app.use(express.json());
app.use(cors())
db.sequelize.sync().then(() => {
console.log("Synced")
}).catch(err => console.err(err))
app.get('/', (req, res) => {
res.send('Hello World!')
})
require('./routes/user.route')(app)
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
Это утверждение делает следующее:
db.sequelize.sync().then(() => {
console.log("Synced")
}).catch(err => console.err(err))
проверить, была ли подключена БД Postgres DB
и продолжить ее.
И затем маршруты, которые мы создадим на следующем шаге.
И запуск нашего сервера:
Закомментируйте эту строку
require('./routes/user.route')(app)
и запустите npm run dev
и посмотрите, является ли приложение Synced
и работает ли оно на порту 3000.
если он отображается ниже:
YAYYYY….!!! Теперь вы создали экспресс-сервер.
Шаг 4:
Здесь начинается самое интересное:
- Давайте создадим маршруты
// project/routes/user.route.js
module.exports = app => {
// Import of the controller
const user = require('../controller/user.controller')
// Creating the router instance
const router = require('express').Router();
// TO create the user
router.post('/user', user.create)
// To Login the user using Passport Local Strategy
router.post('/user-passport-login', user.loginWithPassport)
// Pass the router instance to the App.
app.use('/api/v1', router)
}
Каждый маршрут имеет свое собственное определение, давайте создадим наш самый первый контроллер:
// project/controller/user.controller.js
const db = require("../models");
const User = db.user;
const passportLocal = require('../config/passportLocal')
// To create a new user in the DB
function create(req, res) {
const userdata = {
username: req.body.username,
password: req.body.password
}
User.create(userdata).then(data => {
return res.send(data)
}).catch(err => {
console.warn(err)
})
}
// To Login the user using Passport
async function loginWithPassport(req, res) {
return await passportLocal.authenticate('local', function (err, response) {
if (response) {
return res.send({
msg: "Login Success",
})
}
if (!response) {
return res.send({
msg: "Failed"
})
}
})(req, res)
}
подождите…!!!
почему эта строка:
})(req, res)
loginWithPassport
— это самовызывающаяся функция, которая будет иметь req
и res
в качестве параметров, так как нам нужно вернуть вычисленный ответ от контроллера к API, нам также нужны параметры запроса.
Шаг 5:
Давайте теперь создадим наши Models
:
// project/models/user.model.js
var bcrypt = require('bcrypt-nodejs');
module.exports = (sequelize, DataTypes) => {
// To get the feasiblity of the Sequelize ORM
const User = sequelize.define("user", {
username: {
type: DataTypes.STRING,
primaryKey: true
},
password: {
type: DataTypes.STRING
},
});
// It will convert each password into the Hashed String for maintaining the security
User.beforeSave((user) => {
if (user.changed('password')) {
user.password = bcrypt.hashSync(user.password, bcrypt.genSaltSync(10), null)
}
})
// It will compare the password to the passed string using the bcrypt algo, and will return the result
User.prototype.comparePassowrd = function (pass, cb) {
bcrypt.compare(pass, this.password, function (err, isMatch) {
if (err) {
return cb(err)
}
cb(null, isMatch)
})
}
return User;
};
Мы создали модель, но сейчас она не используется, это просто схема, теперь давайте сделаем самую сложную часть, создадим таблицу БД в pgAdmin, используя следующий код:
// project/models/index.js
const dbConfig = require('../db.config')
const Sequelize = require('sequelize')
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
host: dbConfig.HOST,
operatorAliases: false,
dialect: dbConfig.dialect,
pool: dbConfig.pool
})
const db = {}
db.Sequelize = Sequelize
db.sequelize = sequelize
db.user = require('./user.model.js')(sequelize, Sequelize)
module.exports = db;
dbConfig.js
// project/dbConfig.js
module.exports = {
HOST: "localhost",
USER: "harishsoni",
PASSWORD: "admin",
DB: "testDB",
dialect: "postgres",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
Вот строка из index.js, которая использует вышеуказанную секвелизацию и синхронизацию БД:
const db = require('./models')
Шаг 3:
Теперь заключительная часть — создадим файл passportLocal.js
, который будет содержать основную бизнес-логику для проверки аутентификации при использовании.
// project/config/passportLocal.js
const passport = require('passport')
const LocalStratery = require('passport-local').Strategy
const db = require('../models')
// Creating the passport instance to be used from the controller.
passport.use(new LocalStratery({
// if you use any different name for the username field, you can pass the key here
usernameField: 'username'
}, async function (username, password, done) {
// findByPk is a Sequelize function which returns the data if it finds the primary key with the value passed
return await db.user.findByPk(username).then(async data => {
// Check if the user is there in the DB:
if (!data) {
return done(null, null)
}
// If the user is correct, then let's see if he has entered the correct password.
await data.comparePassowrd(password, (err, userData) => {
return done(null, userData)
})
}).catch(err => { throw err })
}))
// For Storing the user id in the session {req.session.passport.user = {id: '..'}}
passport.serializeUser(function (user, cb) {
cb(null, user)
})
// For checking if the user has an active session.
passport.deserializeUser(function (obj, cb) {
cb(null, obj)
})
module.exports = passport
Вот как будет выглядеть конфигурация паспорта для входа пользователя в систему
В итоге мы получим что-то вроде этого:
project
│ index.js
│ db.config.js
│ package.json
│
└───models
│ user.model.js
│ index.js
│
└───config
│ passportLocal.js
│
└───controller
│ user.controller.js
│
└───routes
user.route.js
🥳🥳🥳 Мы закончили с настройкой, теперь время запустить и посмотреть, работает ли код (если работает, то бог знает как, а если нет, то нам нужно знать почему 😂 😂 😂 😂 😂 😂 😂).
🤞🤞 Here we gooooooooo…..!!!!
🧐🧐🧐 Это сработало::::::::::::
Давайте проверим API СЕЙЧАС:
🤞🤞🤞🤞🤞🤞🤞🤞🤞🤞
Да, это сработало: 😎😎😇😇😇
Any suggestion are welcome:
Ссылка на репо: https://github.com/harish9312/passport-auth-node