Τρόπος ελέγχου ταυτότητας και εξουσιοδότησης χρήστη χρησιμοποιώντας JWT στο NodeJS

Ο έλεγχος ταυτότητας και η εξουσιοδότηση είναι η βασική έννοια της ασφάλειας του υπολογιστή. Χρησιμοποιείτε τα διαπιστευτήριά σας (όπως όνομα χρήστη και κωδικό πρόσβασης) για να αποδείξετε την ταυτότητά σας και να προσδιορίσετε τον εαυτό σας ως εγγεγραμμένος χρήστης και στη συνέχεια να αποκτήσετε πρόσθετα προνόμια.

Αυτό ισχύει επίσης όταν συνδέεστε σε διαδικτυακές υπηρεσίες χρησιμοποιώντας τους λογαριασμούς σας στο Facebook ή στο Google.

Σε αυτό το άρθρο, πρόκειται να δημιουργήσουμε ένα Nodejs API με έλεγχο ταυτότητας JWT (JSON Web Tokens). Τα εργαλεία που πρόκειται να χρησιμοποιήσουμε σε αυτό το σεμινάριο είναι:

  • Expressjs
  • Βάση δεδομένων MongoDB
  • Μαγκούστα
  • Dotenv
  • Bcryptjs
  • Jsonwebtoken

Έλεγχος ταυτότητας Vs. Εξουσιοδότηση

Τι είναι ο έλεγχος ταυτότητας;

Ο έλεγχος ταυτότητας είναι η διαδικασία αναγνώρισης χρηστών με την απόκτηση διαπιστευτηρίων όπως email, κωδικό πρόσβασης και διακριτικά. Τα δεδομένα διαπιστευτηρίων συγκρίνονται με τα διαπιστευτήρια του εγγεγραμμένου χρήστη, τα οποία είναι διαθέσιμα στο αρχείο του τοπικού συστήματος υπολογιστή ή σε οποιεσδήποτε βάσεις δεδομένων. Εάν τα δεδομένα διαπιστευτηρίων ταιριάζουν με τα διαθέσιμα δεδομένα στη βάση δεδομένων, η διαδικασία ελέγχου ταυτότητας ολοκληρώνεται και ο χρήστης επιτρέπεται να έχει πρόσβαση στους πόρους.

Τι είναι η Εξουσιοδότηση;

Η εξουσιοδότηση πραγματοποιείται μετά τον έλεγχο ταυτότητας. Κάθε εξουσιοδότηση πρέπει να έχει μια διαδικασία ελέγχου ταυτότητας. Είναι η διαδικασία που επιτρέπει στους χρήστες να έχουν πρόσβαση σε πόρους από τα συστήματα ή έναν ιστότοπο. Σε αυτό το σεμινάριο, θα εξουσιοδοτήσουμε τους συνδεδεμένους χρήστες να έχουν πρόσβαση στα δεδομένα του χρήστη. Εάν ο χρήστης δεν είναι συνδεδεμένος, δεν θα μπορεί να χρησιμοποιήσει την πρόσβαση στα δεδομένα.

Τα καλύτερα παραδείγματα εξουσιοδότησης είναι οι πλατφόρμες κοινωνικών μέσων όπως το Facebook και το Twitter. Δεν μπορείτε να αποκτήσετε πρόσβαση σε περιεχόμενο μέσων κοινωνικής δικτύωσης χωρίς να έχετε λογαριασμό.

Ένα άλλο παράδειγμα εξουσιοδότησης είναι το περιεχόμενο που βασίζεται σε συνδρομή, ο έλεγχος ταυτότητας μπορεί να γίνει με τη σύνδεση στον ιστότοπο, αλλά δεν θα έχετε εξουσιοδότηση πρόσβασης στο περιεχόμενο έως ότου δεν έχετε εγγραφεί.

Προαπαιτούμενο

Πριν προχωρήσετε, υποθέτω ότι έχετε μια βασική κατανόηση της Javascript και του MongoDB και καλή γνώση του Nodejs.

Βεβαιωθείτε ότι έχετε εγκαταστήσει κόμβο και npm στον τοπικό σας υπολογιστή. Για να ελέγξετε εάν τα node και npm είναι εγκατεστημένα στον υπολογιστή σας, ανοίξτε τη γραμμή εντολών και πληκτρολογήστε node -v και npm -v. Αυτό θα πρέπει να δείχνει το ακόλουθο αποτέλεσμα.

Οι εκδόσεις σας μπορεί να διαφέρουν από τις δικές μου. Η λήψη του NPM γίνεται αυτόματα με τον κόμβο. Αν δεν το έχετε κατεβάσει ακόμα, κατεβάστε το από το Ιστότοπος NodeJS.

Θα χρειαστείτε ένα IDE (ενσωματωμένο περιβάλλον ανάπτυξης) για να γράψετε κώδικα. Σε αυτό το σεμινάριο, χρησιμοποιώ τον επεξεργαστή κώδικα VS. Εάν έχετε άλλο, μπορείτε να το χρησιμοποιήσετε και αυτό. Εάν δεν έχετε εγκατεστημένο IDE στον υπολογιστή σας, μπορείτε να το κατεβάσετε από το Ιστοσελίδα του Visual Studio. Κατεβάστε το με βάση το τοπικό σας σύστημα.

  Πώς να διαγράψετε έναν λογαριασμό Badoo

Ρύθμιση έργου

Δημιουργήστε ένα όνομα φακέλου 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.

Η δρομολόγηση αναφέρεται στον τρόπο με τον οποίο μια εφαρμογή ανταποκρίνεται στα αιτήματα του πελάτη. Θα χρησιμοποιήσουμε τη λειτουργία express router για να δημιουργήσουμε διαδρομές.

Οι μέθοδοι δρομολόγησης λαμβάνουν συνήθως δύο ορίσματα. Η πρώτη είναι η διαδρομή και η δεύτερη είναι η συνάρτηση επανάκλησης για να ορίσετε τι θα έκανε αυτή η διαδρομή κατόπιν αιτήματος του πελάτη.

Λαμβάνει επίσης ένα τρίτο όρισμα ως συνάρτηση ενδιάμεσου λογισμικού όταν χρειάζεται, όπως στη διαδικασία ελέγχου ταυτότητας. Καθώς δημιουργούμε πιστοποιημένο API, θα χρησιμοποιήσουμε επίσης τη λειτουργία ενδιάμεσου λογισμικού για την εξουσιοδότηση και τον έλεγχο ταυτότητας των χρηστών.

Τώρα θα δημιουργήσουμε δύο φακέλους με το όνομα routes και models. Μέσα στις διαδρομές, δημιουργήστε ένα όνομα αρχείου 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 tokens

Τι είναι το JWT;

Τα JSON web tokens (JWT) είναι μια βιβλιοθήκη javascript που δημιουργεί και επαληθεύει διακριτικά. Είναι ένα ανοιχτό πρότυπο που χρησιμοποιείται για την κοινή χρήση πληροφοριών μεταξύ δύο μερών – ενός πελάτη και ενός διακομιστή. Θα χρησιμοποιήσουμε δύο λειτουργίες του JWT. Η πρώτη συνάρτηση είναι το σύμβολο για τη δημιουργία ενός νέου διακριτικού και η δεύτερη συνάρτηση είναι η επαλήθευση για την επαλήθευση του διακριτικού.

  Πώς να διατηρήσετε ενημερωμένα τα Mods "Sims 4".

Τι είναι το 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}`);
})

Δημιουργία ενδιάμεσου λογισμικού για έλεγχο ταυτότητας χρήστη

Τι είναι το ενδιάμεσο λογισμικό;

Το Middleware είναι μια συνάρτηση που έχει πρόσβαση στο αίτημα, το αντικείμενο απόκρισης και την επόμενη συνάρτηση στον κύκλο αίτησης-απόκρισης. Η επόμενη συνάρτηση καλείται όταν ολοκληρωθεί η εκτέλεση της συνάρτησης. Όπως ανέφερα παραπάνω, χρησιμοποιήστε το next() όταν πρέπει να εκτελέσετε μια άλλη συνάρτηση επανάκλησης ή συνάρτηση ενδιάμεσου λογισμικού.

  Πώς να προγραμματίσετε μηνύματα στο Slack

Τώρα δημιουργήστε έναν φάκελο με το όνομα 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 για να διαμορφώσετε το cookieParser στην εφαρμογή σας. Το cookieParser σάς βοηθά να αποκτήσετε πρόσβαση στο διακριτικό που είναι αποθηκευμένο στο cookie. Εάν δεν έχετε διαμορφώσει το cookieParser στην εφαρμογή nodejs, δεν θα μπορείτε να έχετε πρόσβαση στα cookie από τις κεφαλίδες του αντικειμένου αιτήματος. Τώρα, γράψτε στο τερματικό για λήψη του προγράμματος ανάλυσης cookie.

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 είναι ένα εργαλείο λογισμικού για το σχεδιασμό, την κατασκευή, την ανάπτυξη και τη δοκιμή API.

Εάν δεν έχετε κατεβάσει τον ταχυδρόμο στον υπολογιστή σας, κάντε λήψη του από το ιστοσελίδα ταχυδρόμων.

Τώρα ανοίξτε τον ταχυδρόμο και δημιουργήστε ένα όνομα συλλογής nodeAPItest και μέσα σε αυτό, δημιουργήστε τρία αιτήματα: εγγραφή, σύνδεση και χρήστης. Θα πρέπει να έχετε τα ακόλουθα αρχεία.

Όταν στέλνετε δεδομένα JSON στο “localhost:5000/api/register”, θα λάβετε το ακόλουθο αποτέλεσμα.

Καθώς δημιουργούμε και αποθηκεύουμε διακριτικά σε cookies επίσης κατά την εγγραφή, μπορείτε να έχετε τα στοιχεία χρήστη όταν ζητάτε τη διαδρομή “localhost:5000/api/user”. Μπορείτε να ελέγξετε τα υπόλοιπα αιτήματα στο POSTMAN.

Αν θέλετε τον πλήρη κωδικό μπορείτε να τον πάρετε από το δικό μου λογαριασμό github.

συμπέρασμα

Σε αυτό το σεμινάριο, μάθαμε πώς να εφαρμόζουμε έλεγχο ταυτότητας στο NodeJS API χρησιμοποιώντας διακριτικά JWT. Εξουσιοδοτήσαμε επίσης τους χρήστες να έχουν πρόσβαση στα δεδομένα χρήστη.

ΚΑΛΗ ΚΩΔΙΚΟΠΟΙΗΣΗ!