Как да удостоверите и упълномощите потребител с помощта на JWT в NodeJS

Удостоверяването и оторизацията е основната концепция на компютърната сигурност. Вие използвате своите идентификационни данни (като потребителско име и парола), за да докажете самоличността си и да се идентифицирате като регистриран потребител, след което да получите допълнителни привилегии.

Това важи и когато влизате в онлайн услуги, използвайки своите акаунти във Facebook или Google.

В тази статия ще изградим Nodejs API с JWT (JSON уеб токени) удостоверяване. Инструментите, които ще използваме в този урок са:

  • Expressjs
  • MongoDB база данни
  • Мангуста
  • Дотенв
  • Bcryptjs
  • Jsonwebtoken

Удостоверяване Vs. Упълномощаване

Какво е удостоверяване?

Удостоверяването е процес на идентифициране на потребителите чрез получаване на идентификационни данни като имейл, парола и токени. Дадените идентификационни данни се сравняват с идентификационните данни на регистрирания потребител, които са налични във файла на локалната компютърна система или всякакви бази данни. Ако дадените идентификационни данни съвпадат с наличните данни в базата данни, процесът на удостоверяване е завършен и на потребителя е разрешен достъп до ресурсите.

Какво е оторизация?

Упълномощаването става след удостоверяване. Всяко разрешение трябва да има процес на удостоверяване. Това е процес на позволяване на потребителите да имат достъп до ресурси от системите или уебсайт. В този урок ще упълномощим влезли потребители за достъп до данните на потребителя. Ако потребителят не е влязъл, той няма да може да използва достъп до данните.

Най-добрите примери за оторизация са социални медийни платформи като Facebook и Twitter. Не можете да получите достъп до съдържание в социалните медии, без да имате акаунт.

Друг пример за оторизация е базирано на абонамент съдържание, вашето удостоверяване може да бъде направено чрез влизане в уебсайта, но няма да бъдете упълномощени за достъп до съдържанието, докато не сте се абонирали.

Предпоставка

Преди да продължите напред, предполагам, че имате основни познания за Javascript и MongoDB и добри познания за Nodejs.

Уверете се, че сте инсталирали node и npm на вашата локална машина. За да проверите дали node и npm са инсталирани на вашия компютър, отворете командния ред и въведете node -v и npm -v. Това трябва да покаже следния резултат.

Вашите версии може да се различават от моите. NPM автоматично се изтегля с възела. Ако все още не сте го изтеглили, изтеглете го от NodeJS уебсайт.

Ще ви трябва IDE (интегрирана среда за разработка), за да пишете код. В този урок използвам редактор на VS код. Ако имате друг, можете да използвате и него. Ако нямате инсталирано IDE на вашия компютър, можете да го изтеглите от Уебсайт на Visual Studio. Изтеглете го въз основа на вашата локална система.

  Вижте коя песен се е пускала по време на сцена във филм или телевизионно шоу

Настройка на проекта

Създайте име на папка nodeapi навсякъде на вашия локален компютър и след това я отворете с vs-code. Отворете vs-code терминала и след това инициализирайте мениджъра на пакети на възли, като напишете.

npm init -y

Уверете се, че сте в директорията nodeapi.

Горната команда ще създаде файл package.json, който съдържа всички зависимости, които ще използваме в този проект.

Сега ще изтеглим всички пакети, споменати по-горе, сега напишете и ги въведете в терминала.

npm install express dotenv jsonwebtoken mongoose bcryptjs

Сега ще имате файлове и папки, както е показано по-долу.

Създаване на сървър и свързване на база данни

Сега създайте файл с име index.js и папка с име config. В config създайте два файла с име conn.js за свързване към базата данни и config.env за деклариране на променливи на средата. Напишете дадения код по-долу в съответните файлове.

index.js

const express = require('express');
const dotenv = require('dotenv');

//Configure dotenv files above using any other library and files
dotenv.config({path:'./config/config.env'}); 

//Creating an app from express
const app = express();

//Using express.json to get request of json data
app.use(express.json());



//listening to the server
app.listen(process.env.PORT,()=>{
    console.log(`Server is listening at ${process.env.PORT}`);
})

Ако използвате dotenv, тогава го конфигурирайте във вашия файл index.js, преди да извикате други файлове, които използват променливи на средата.

conn.js

const mongoose = require('mongoose');

mongoose.connect(process.env.URI, 
    { useNewUrlParser: true,
     useUnifiedTopology: true })
    .then((data) => {
        console.log(`Database connected to ${data.connection.host}`)
})

config.env

URI = 'mongodb+srv://ghulamrabbani883:[email protected]/?retryWrites=true&w=majority'
PORT = 5000

Използвам mongo-DB Atlas URI, можете да използвате и localhost.

Създаване на модели и маршрути

Моделът е оформление на вашите данни в базата данни Mongo-DB и ще се съхранява като JSON документ. За да създадем модел, ще използваме схемата mongoose.

Маршрутизирането се отнася до това как дадено приложение отговаря на клиентски заявки. Ще използваме функцията експресен рутер за създаване на маршрути.

Методите за маршрутизиране обикновено приемат два аргумента. Първият е маршрут, а вторият е функцията за обратно извикване, за да се определи какво ще направи този маршрут по заявка на клиента.

Той също така приема трети аргумент като функция на междинен софтуер, когато е необходимо, като в процеса на удостоверяване. Тъй като изграждаме удостоверен API, ще използваме и функцията на междинния софтуер за оторизиране и удостоверяване на потребители.

Сега ще създадем две папки с имена routes и models. Вътре в routes създайте име на файл userRoute.js и вътре в папката models създайте име на файл userModel.js. След като създадете файлове, напишете следния код в съответните файлове.

userModel.js

const mongoose = require('mongoose');

//Creating Schema using mongoose
const userSchema = new mongoose.Schema({
    name: {
        type:String,
        required:true,
        minLength:[4,'Name should be minimum of 4 characters']
    },
    email:{
        type:String,
        required:true,
        unique:true,
    },
    password:{
        type:String,
        required:true,
        minLength:[8,'Password should be minimum of 8 characters']
    },
    token:{
        type:String
    }
})

//Creating models
const userModel = mongoose.model('user',userSchema);
module.exports = userModel;

userRoute.js

const express = require('express');
//Creating express router
const route = express.Router();
//Importing userModel
const userModel = require('../models/userModel');

//Creating register route
route.post('/register',(req,res)=>{

})
//Creating login routes
route.post('/login',(req,res)=>{

})

//Creating user routes to fetch users data
route.get('/user',(req,res)=>{

})

Внедряване на функционалност на маршрута и създаване на JWT токени

Какво е JWT?

JSON уеб токени (JWT) е библиотека на javascript, която създава и проверява токени. Това е отворен стандарт, използван за споделяне на информация между две страни – клиент и сървър. Ще използваме две функции на JWT. Първата функция е sign за създаване на нов токен, а втората функция е verify за проверка на токена.

  Как да зададете автоматична дата на изтичане на връзките в Google Drive

Какво е bcryptjs?

Bcryptjs е функция за хеширане, създадена от Niels Provos и David Mazières. Той използва хеш алгоритъм за хеширане на паролата. Той има две най-често срещани функции, които ще използваме в този проект. Първата bcryptjs функция е хеш за генериране на хеш стойност, а втората функция е функция за сравняване за сравняване на пароли.

Внедрете функционалност на маршрута

Функцията за обратно извикване при маршрутизиране приема три аргумента, заявка, отговор и следваща функция. Следващият аргумент не е задължителен; предавайте това само когато имате нужда от това. Тези аргументи трябва да бъдат в заявката, отговора и следващата поръчка. Сега променете файловете userRoute.js, config.env и index.js със следните кодове.

userRoute.js

//Requiring all the necessary files and libraries
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

//Creating express router
const route = express.Router();
//Importing userModel
const userModel = require('../models/userModel');

//Creating register route
route.post("/register", async (req, res) => {

    try {
        const { name, email, password } = req.body;
        //Check emptyness of the incoming data
        if (!name || !email || !password) {
            return res.json({ message: 'Please enter all the details' })
        }

        //Check if the user already exist or not
        const userExist = await userModel.findOne({ email: req.body.email });
        if (userExist) {
            return res.json({ message: 'User already exist with the given emailId' })
        }
        //Hash the password
        const salt = await bcrypt.genSalt(10);
        const hashPassword = await bcrypt.hash(req.body.password, salt);
        req.body.password = hashPassword;
        const user = new userModel(req.body);
        await user.save();
        const token = await jwt.sign({ id: user._id }, process.env.SECRET_KEY, {
            expiresIn: process.env.JWT_EXPIRE,
        });
        return res.cookie({ 'token': token }).json({ success: true, message: 'User registered successfully', data: user })
    } catch (error) {
        return res.json({ error: error });
    }

})
//Creating login routes
route.post('/login', async (req, res) => {
    try {
        const { email, password } = req.body;
        //Check emptyness of the incoming data
        if (!email || !password) {
            return res.json({ message: 'Please enter all the details' })
        }
        //Check if the user already exist or not
        const userExist = await userModel.findOne({email:req.body.email});
        if(!userExist){
            return res.json({message:'Wrong credentials'})
        }
        //Check password match
        const isPasswordMatched = await bcrypt.compare(password,userExist.password);
        if(!isPasswordMatched){
            return res.json({message:'Wrong credentials pass'});
        }
        const token = await jwt.sign({ id: userExist._id }, process.env.SECRET_KEY, {
            expiresIn: process.env.JWT_EXPIRE,
        });
        return res.cookie({"token":token}).json({success:true,message:'LoggedIn Successfully'})
    } catch (error) {
        return res.json({ error: error });
    }

})

//Creating user routes to fetch users data
route.get('/user', async (req, res) => {
    try {
        const user  = await userModel.find();
        if(!user){
            return res.json({message:'No user found'})
        }
        return res.json({user:user})
    } catch (error) {
        return res.json({ error: error });  
    }
})

module.exports = route;

Ако използвате функцията Async, използвайте блок try-catch, в противен случай ще изведе необработена грешка при отхвърляне на обещание.

config.env

URI = 'mongodb+srv://ghulamrabbani883:[email protected]/?retryWrites=true&w=majority'
PORT = 5000
SECRET_KEY = KGGK>HKHVHJVKBKJKJBKBKHKBMKHB
JWT_EXPIRE = 2d

index.js

const express = require('express');
const dotenv = require('dotenv');

//Configure dotenv files above using any other library and files
dotenv.config({path:'./config/config.env'}); 
require('./config/conn');
//Creating an app from express
const app = express();
const route = require('./routes/userRoute');

//Using express.json to get request of json data
app.use(express.json());
//Using routes

app.use('/api', route);

//listening to the server
app.listen(process.env.PORT,()=>{
    console.log(`Server is listening at ${process.env.PORT}`);
})

Създаване на междинен софтуер за удостоверяване на потребителя

Какво е междинен софтуер?

Мидълуерът е функция, която има достъп до заявката, обекта за отговор и следващата функция в цикъла заявка-отговор. Следващата функция се извиква, когато изпълнението на функцията приключи. Както споменах по-горе, използвайте next(), когато трябва да изпълните друга функция за обратно извикване или функция на мидълуер.

  Изтеглете файлове директно на вашия iPhone и ги преглеждайте в библиотека [Paid]

Сега създайте папка с име Middleware и вътре в нея създайте име на файл като auth.js и напишете следния код.

auth.js

const userModel = require('../models/userModel');
const jwt = require('jsonwebtoken');
const isAuthenticated = async (req,res,next)=>{
    try {
        const {token} = req.cookies;
        if(!token){
            return next('Please login to access the data');
        }
        const verify = await jwt.verify(token,process.env.SECRET_KEY);
        req.user = await userModel.findById(verify.id);
        next();
    } catch (error) {
       return next(error); 
    }
}

module.exports = isAuthenticated;

Сега инсталирайте библиотеката на cookie-parser, за да конфигурирате cookieParser във вашето приложение. cookieParser ви помага да получите достъп до маркера, съхранен в бисквитката. Ако нямате конфигуриран cookieParser във вашето приложение nodejs, няма да имате достъп до бисквитките от заглавките на обекта на заявката. Сега напишете в терминала, за да изтеглите анализатор на бисквитки.

npm i cookie-parser

Сега имате инсталиран cookieParser. Конфигурирайте приложението си, като модифицирате файла index.js и добавите междинен софтуер към маршрута „/user/“.

файл index.js

const cookieParser = require('cookie-parser');
const express = require('express');
const dotenv = require('dotenv');

//Configure dotenv files above using any other library and files
dotenv.config({path:'./config/config.env'}); 
require('./config/conn');
//Creating an app from express
const app = express();
const route = require('./routes/userRoute');

//Using express.json to get request of json data
app.use(express.json());
//Configuring cookie-parser
app.use(cookieParser()); 

//Using routes
app.use('/api', route);

//listening to the server
app.listen(process.env.PORT,()=>{
    console.log(`Server is listening at ${process.env.PORT}`);
})

userRoute.js

//Requiring all the necessary files and libraries
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const isAuthenticated = require('../middleware/auth');

//Creating express router
const route = express.Router();
//Importing userModel
const userModel = require('../models/userModel');

//Creating user routes to fetch users data
route.get('/user', isAuthenticated, async (req, res) => {
    try {
        const user = await userModel.find();
        if (!user) {
            return res.json({ message: 'No user found' })
        }
        return res.json({ user: user })
    } catch (error) {
        return res.json({ error: error });
    }
})

module.exports = route;

Маршрутът “/user” е достъпен само когато потребителят е влязъл.

Проверка на API на POSTMAN

Преди да проверите API, трябва да промените файла package.json. Добавете следните редове код.

"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "start": "node index.js",
    "dev": "nodemon index.js"
  },

Можете да стартирате сървъра, като напишете npm start, но той ще се стартира само веднъж. За да поддържате сървъра си работещ, докато променяте файлове, ще ви трябва nodemon. Изтеглете го, като въведете в терминала

npm install -g nodemon

-g флаг ще изтегли nodemon глобално във вашата локална система. Не е нужно да го изтегляте отново и отново за всеки нов проект.

За да стартирате сървъра, въведете npm run dev в терминала. Ще получите следния резултат.

Най-накрая вашият код е завършен и сървърът работи правилно, отидете при пощальона и проверете дали работи.

Какво е POSTMAN?

POSTMAN е софтуерен инструмент за проектиране, изграждане, разработване и тестване на API.

Ако не сте изтеглили пощальона на вашия компютър, изтеглете го от уебсайт на пощальона.

Сега отворете пощальона и създайте име на колекция nodeAPItest и вътре в него създайте три заявки: регистрация, влизане и потребител. Трябва да имате следните файлове.

Когато изпратите JSON данни към „localhost:5000/api/register“, ще получите следния резултат.

Тъй като ние също създаваме и запазваме токени в бисквитки по време на регистрация, можете да имате подробности за потребителя, когато поискате маршрута „localhost:5000/api/user“. Останалите заявки можете да проверите на POSTMAN.

Ако искате пълния код, можете да го получите от моя акаунт в github.

Заключение

В този урок научихме как да прилагаме удостоверяване към NodeJS API с помощта на JWT токени. Също така упълномощихме потребителите за достъп до потребителските данни.

ПРИЯТНО КОДИРАНЕ!