שולחים נתונים ממקום למקום? בשביל השקט הנפשי שלך, והגנת המשתמשים שלך, עליך לאבטח אותו באמצעות JWT.

כאשר אתה בונה אפליקציה, חיוני שתגן על נתונים רגישים מפני גישה לא מורשית. יישומי אינטרנט, ניידים וענן מודרניים רבים משתמשים בממשקי API של REST כאמצעי התקשורת העיקרי. כתוצאה מכך, חיוני לעצב ולפתח ממשקי API אחוריים עם אבטחה בחזית.

גישה יעילה אחת לאבטחת ממשק API של REST כוללת JSON Web Tokens (JWTs). אסימונים אלה מציעים מנגנון חזק לאימות והרשאה של משתמשים, המסייעים בהגנה על משאבים מוגנים מפני גישה של גורמים זדוניים.

מה הם אסימוני אינטרנט של JSON?

JSON Web Token (JWT) הוא תקן אבטחה בשימוש נרחב. היא מספקת שיטה תמציתית ועצמאית להעברת נתונים מאובטחת בין אפליקציית לקוח למערכת עורפית.

REST API יכול להשתמש ב-JWTs כדי לזהות ולאמת משתמשים בצורה מאובטחת כאשר הם מבצעים בקשות HTTP לגישה למשאבים מוגנים.

אסימון אינטרנט של JSON מורכב משלושה חלקים נפרדים: הכותרת, המטען והחתימה. הוא מקודד כל חלק ומשרשר אותם באמצעות נקודה (".").

הכותרת מתארת ​​את האלגוריתם ההצפנה המשמש לחתימה על האסימון, בעוד המטען מכיל נתונים על המשתמש וכל מטא נתונים נוספים.

instagram viewer

לבסוף, החתימה, המחושבת באמצעות הכותרת, המטען והמפתח הסודי, מבטיחה את השלמות והאותנטיות של האסימון.

עם היסודות של JWTs מחוץ לדרך, בואו נבנה Node.js REST API וליישם JWTs.

הגדר יישום Express.js ומסד נתונים של MongoDB

תוכל לגלות כאן כיצד לבנות אימות פשוט REST API שמטפל גם בפונקציונליות הרישום וגם בכניסה. ברגע שתהליך הכניסה מאמת משתמש, הוא אמור להיות מסוגל לשלוח בקשות HTTP לנתיב API מוגן.

אתה יכול למצוא את הקוד של הפרויקט בזה מאגר GitHub.

להתחיל, ליצור שרת אינטרנט Express, והתקן את החבילות הבאות:

npm התקנת cors dotenv bycrpt mongoose cookie-parser crypto jsonwebtoken mongodb

הַבָּא, צור מסד נתונים MongoDB אוֹ להגדיר אשכול MongoDB בענן. לאחר מכן העתק את מחרוזת חיבור מסד הנתונים, צור א .env קובץ בספריית השורש, והדבק במחרוזת החיבור:

CONNECTION_STRING="מחרוזת חיבור"

הגדר את חיבור מסד הנתונים

ליצור חדש utils/db.js קובץ בספריית השורש של תיקיית הפרויקט שלך. בקובץ זה, הוסף את הקוד הבא כדי ליצור את חיבור מסד הנתונים באמצעות Mongoose.

const נמייה = לִדרוֹשׁ('נְמִיָה');

const connectDB = אסינכרון () => {
לְנַסוֹת {
לְהַמתִין mongoose.connect (process.env. מחרוזת חיבור);
לְנַחֵם.עֵץ("מחובר ל-MongoDB!");
} לתפוס (שגיאה) {
לְנַחֵם.שְׁגִיאָה("שגיאה בחיבור ל-MongoDB:", שגיאה);
}
};

מודול.exports = connectDB;

הגדר את מודל הנתונים

הגדר סכימת נתוני משתמש פשוטה באמצעות Mongoose. בספריית השורש, צור חדש model/user.model.js קובץ והוסיפו את הקוד הבא.

const נמייה = לִדרוֹשׁ('נְמִיָה');

const userSchema = חָדָשׁ נְמִיָה. סכֵימָה({
שם משתמש: חוּט,
סיסמה: {
סוּג: חוּט,
נדרש: נָכוֹן,
ייחודי: נָכוֹן,
},
});

const משתמש = mongoose.model("מִשׁתַמֵשׁ", userSchema);
מודול.exports = משתמש;

הגדר את הבקרים עבור נתיבי ה-API

פונקציות הבקר ינהלו את הרישום והכניסה; הם חלק מהותי מהתוכנית לדוגמה הזו. בספריית השורש, צור א controllers/userControllers.js קובץ והוסיפו את הקוד הבא:

  1. הגדר את בקר רישום המשתמש.
    const משתמש = לִדרוֹשׁ('../models/user.model');
    const bcrypt = לִדרוֹשׁ('bcrypt');
    const {generToken } = לִדרוֹשׁ('../middleware/auth');

    exports.registerUser = אסינכרון (req, res) => {
    const { שם משתמש, סיסמה } = req.body;

    לְנַסוֹת {
    const hash = לְהַמתִין bcrypt.hash (סיסמה, 10);
    לְהַמתִין User.create({ שם משתמש, סיסמה: hash });
    res.status(201).לִשְׁלוֹחַ({ הוֹדָעָה: 'משתמש נרשם בהצלחה' });
    } לתפוס (שגיאה) {
    לְנַחֵם.log (שגיאה);
    res.status(500).לִשְׁלוֹחַ({ הוֹדָעָה: 'התרחשה שגיאה!! ' });
    }
    };

    קטע קוד זה מאחסן את הסיסמה שסופקה באמצעות bcrypt ולאחר מכן יוצר רשומת משתמש חדשה במסד הנתונים, המאחסן את שם המשתמש והסיסמה המגובבת. אם ההרשמה הצליחה, היא שולחת תגובה עם הודעת הצלחה.
  2. הגדר בקר כניסה לניהול תהליך הכניסה של המשתמש:
    exports.loginUser = אסינכרון (req, res) => {
    const { שם משתמש, סיסמה } = req.body;

    לְנַסוֹת {
    const משתמש = לְהַמתִין User.findOne({ שם משתמש });

    אם (!משתמש) {
    לַחֲזוֹר res.status(404).לִשְׁלוֹחַ({ הוֹדָעָה: 'המשתמש לא נמצא' });
    }

    const passwordMatch = לְהַמתִין bcrypt.compare (סיסמה, user.password);

    אם (!passwordMatch) {
    לַחֲזוֹר res.status(401).לִשְׁלוֹחַ({ הוֹדָעָה: 'נתוני כניסה שגויים' });
    }

    const מטען = { זהות המשתמש: זהות המשתמש };
    const token = generToken (מטען);
    res.cookie('אֲסִימוֹן', אסימון, { http בלבד: נָכוֹן });
    res.status(200).json({ הוֹדָעָה: 'התחברת בהצלחה'});
    } לתפוס (שגיאה) {
    לְנַחֵם.log (שגיאה);
    res.status(500).לִשְׁלוֹחַ({ הוֹדָעָה: 'אירעה שגיאה בעת הכניסה' });
    }
    };

    כאשר משתמש שולח בקשה ל- /login מסלול, עליהם להעביר את אישורי האימות שלהם בגוף הבקשה. לאחר מכן הקוד מאמת את האישורים הללו ויוצר אסימון אינטרנט של JSON. האסימון מאוחסן בצורה מאובטחת בעוגייה עם ה- http בלבד הדגל מוגדר כאמת. זה מונע מ-JavaScript בצד הלקוח לגשת לאסימון, ומגן מפני התקפות פוטנציאליות של סקריפטים בין-אתרים (XSS).
  3. לבסוף, הגדר מסלול מוגן:
    exports.getUsers = אסינכרון (req, res) => {
    לְנַסוֹת {
    const משתמשים = לְהַמתִין User.find({});
    res.json (משתמשים);
    } לתפוס (שגיאה) {
    לְנַחֵם.log (שגיאה);
    res.status(500).לִשְׁלוֹחַ({ הוֹדָעָה: 'התרחשה שגיאה!!' });
    }
    };
    על ידי אחסון ה-JWT בקובץ cookie, בקשות API עוקבות מהמשתמש המאומת יכללו אוטומטית את האסימון, מה שיאפשר לשרת לאמת ולאשר את הבקשות.

צור תוכנת אימות לאימות

כעת, לאחר שהגדרתם בקר כניסה שיוצר אסימון JWT לאחר אימות מוצלח, הגדר פונקציות אימות תוכנת ביניים שייצרו ויאמתו את אסימון JWT.

בספריית השורש, צור תיקיה חדשה, תוכנת ביניים. בתוך תיקיה זו, הוסף שני קבצים: auth.js ו config.js.

הוסף את הקוד הזה ל config.js:

const קריפטו = לִדרוֹשׁ('קריפטו');

מודול‎.exports = {
secretKey: crypto.randomBytes(32).toString('hex')
};

קוד זה יוצר מפתח סודי אקראי חדש בכל פעם שהוא פועל. לאחר מכן תוכל להשתמש במפתח סודי זה כדי לחתום ולאמת את האותנטיות של JWTs. לאחר שמשתמש מאומת בהצלחה, צור וחתום JWT עם המפתח הסודי. לאחר מכן השרת ישתמש במפתח כדי לוודא שה-JWT חוקי.

הוסף את הקוד הבא auth.js שמגדיר פונקציות של תוכנת ביניים שמייצרות ומאמתות את ה-JWTs.

const jwt = לִדרוֹשׁ('jsonwebtoken');
const { secretKey } = לִדרוֹשׁ('./config');

const generToken = (מטען) => {
const token = jwt.sign (מטען, secretKey, { פג תוקף ב: 'שעה אחת' });
לַחֲזוֹר אסימון ;
};

const verifyToken = (req, res, next) => {
const token = req.cookies.token;

אם (!token) {
לַחֲזוֹר res.status(401).json({ הוֹדָעָה: 'לא מסופק אסימון' });
}

jwt.verify (אסימון, secretKey, (שגיאה, מפוענח) => {
אם (שגיאה) {
לַחֲזוֹר res.status(401).json({ הוֹדָעָה: 'אסימון לא חוקי' });
}

req.userId = decoded.userId;
הַבָּא();
});
};

מודול.exports = { generateToken, verifyToken };

ה generToken הפונקציה יוצרת JWT על ידי חתימה על מטען באמצעות מפתח סודי וקביעת זמן תפוגה בזמן verifyToken הפונקציה משמשת כתווך כדי לאמת את האותנטיות והתקפות של אסימון שסופק.

הגדר את נתיבי ה-API

ליצור חדש routes/userRoutes.js קובץ בספריית השורש והוסף את הקוד הבא.

const express = לִדרוֹשׁ('אֶקְסְפּרֶס');
const נתב = אקספרס. נתב();
const userControllers = לִדרוֹשׁ('../controllers/userControllers');
const { verifyToken } = לִדרוֹשׁ('../middleware/auth');
router.post('/api/register', userControllers.registerUser);
router.post('/api/login', userControllers.loginUser);
router.get('/api/users', verifyToken, userControllers.getUsers);
מודול.exports = נתב;

עדכן את נקודת הכניסה לשרת שלך

עדכן את שלך server.js קובץ עם הקוד הבא.

const express = לִדרוֹשׁ('אֶקְסְפּרֶס');
const cors = לִדרוֹשׁ('קורס');
const app = express();
const יציאה = 5000;
לִדרוֹשׁ('dotenv').config();
const connectDB = לִדרוֹשׁ('./utils/db');
const cookieParser = לִדרוֹשׁ('מנתח עוגיות');

connectDB();

app.use (express.json());
app.use (express.urlencoded({ מורחב: נָכוֹן }));
app.use (cors());
app.use (cookieParser());
const userroutes = לִדרוֹשׁ('./routes/userRoutes');
app.use('/', UserRoutes);

app.listen (פורט, () => {
לְנַחֵם.עֵץ(`השרת מאזין ל http://localhost:${port}`);
});

כדי לבדוק את REST API, הפוך את שרת הפיתוח ושלח בקשות API לנקודות הקצה שהוגדרו:

node server.js

אבטחת ממשקי API של Node.js REST

אבטחת ממשקי API של Node.js REST חורג משימוש רק ב-JWTs, למרות שהם ממלאים תפקיד מכריע באימות וב אישור, חיוני לאמץ גישת אבטחה הוליסטית לאבטחה כדי להגן על הקצה האחורי שלך מערכות. לצד JWTs, כדאי לשקול גם הטמעת HTTPS להצפנת תקשורת, אימות קלט וחיטוי ועוד רבים אחרים.

על ידי שילוב של אמצעי אבטחה מרובים, אתה יכול להקים מסגרת אבטחה חזקה עבורך ממשקי API של Node.js REST וממזערים את הסיכון של גישה לא מורשית, פרצות נתונים ואבטחה אחרת איומים.