شما می توانید با احراز هویت از کاربران واقعی در برابر کاربران مخرب محافظت کنید. اطمینان حاصل کنید که از بهترین روش ها برای جلوگیری از ایجاد هرگونه حفره امنیتی استفاده می کنید.
احراز هویت کاربر فرآیند تأیید هویت کاربری است که تلاش می کند به برنامه شما دسترسی پیدا کند. این شامل مجوز و انتقال اعتبار برای تأیید صحت کاربر است.
شما می توانید یک مدل ساده احراز هویت کاربر را در Node.js با استفاده از Express، Bcrypt و MongoDB، تنها در چند مرحله پیاده سازی کنید.
مرحله 1: تنظیم محیط توسعه
ابتدا یک پوشه پروژه ایجاد کنید و با اجرای cd در آن قرار دهید:
mkdir user-authentication
cd user-authentication
سپس، npm را در فهرست پروژه خود با اجرای:
npm init -y
پرچم -y npm را مقداردهی اولیه می کند و فایل package.json شما را با تمام پیش فرض هایش ایجاد می کند.
این مدل احراز هویت کاربر به چند وابستگی نیاز دارد.
آنها عبارتند از:
- Express: Express یک چارچوب Node.js است که مجموعه ای قوی از ویژگی ها را برای برنامه های کاربردی وب و موبایل ارائه می دهد. ساخت برنامه های بک اند با Node.js را آسان تر می کند.
- Bcrypt: bcrypt یک بسته npm است که عملکرد هش رمز عبور bcrypt را پیاده سازی می کند. این به شما امکان می دهد تا از رشته های رمز عبور ساده هش ایجاد کنید.
- Mongoose: Mongoose یک کتابخانه مدلسازی دادههای شی MongoDB است. این تعامل بین برنامه شما و پایگاه داده MongoDB را ساده می کند.
- dotenv: dotenv یک بسته وابستگی صفر است که متغیرهای محیطی را از یک فایل .env در process.env بارگیری می کند.
- Validator: اعتبار سنجی بسته ای است که شامل توابع اعتبارسنجی رشته های مختلف است.
- تجزیهکننده بدن: بسته تجزیهکننده بدن، بدنهها را در یک میانافزار قبل از کنترلکنندههای شما تجزیه میکند.
بسته ها را با اجرای:
npm install express bcrypt mongoose dotenv validator body-parser
در مرحله بعد، یک فایل app.js در دایرکتوری ریشه پروژه خود ایجاد کنید و بلوک کد زیر را اضافه کنید تا یک سرور Express اولیه ایجاد کنید:
// app.js
const express = require(&aposexpress&apos);
const app = express();
const bodyParser = require("body-parser");
const port = 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(port, ()=>{
console.log(`App is listening on port ${port}`);
});
این کد با فراخوانی تابع express یک نمونه برنامه اکسپرس ایجاد می کند. سپس از میانافزار تجزیهکننده بدن برای تجزیه درخواستهای ورودی استفاده میکند. سپس با فراخوانی متد listen نمونه express و ارسال متغیر پورت به عنوان آرگومان شروع به گوش دادن به ترافیک در پورت 3000 می کند.
مرحله 2: اتصال برنامه خود به یک پایگاه داده
در فهرست اصلی پروژه خود، یک فایل env. ایجاد کنید و اعتبار MongoDB خود را در آن ذخیره کنید. این امر از افشای اعتبار پایگاه داده شما در کد جلوگیری می کند که می تواند به کاربران مخرب دسترسی به پایگاه داده شما را بدهد.
سپس به فایل app.js خود بروید و mongoose را وارد کنید:
const mongoose = require("mongoose");
سپس import dotenv را فراخوانی کرده و متد config را روی آن فراخوانی کنید:
require("dotenv").config();
فراخوانی متد config در dotenv متغیرهای محیطی را در process.env بارگذاری می کند.
در نهایت، متد connect را در mongoose فراخوانی کنید و URI MongoDB خود را به عنوان آرگومان ارسال کنید:
mongoose.connect(process.env.MONGODB_URI).then(() => {
console.log(&aposConnected to Database Successfully&apos)
})
مرحله 3: ایجاد مدل کاربر
در فهرست اصلی پروژه خود، یک پوشه “models” ایجاد کنید. این جایی است که شما مدل مونگوس خود را ذخیره خواهید کرد:
mkdir models
بعد، یک فایل “userModel” ایجاد کنید و واردهای زیر را اضافه کنید:
const mongoose = require(&aposmongoose&apos)
const { isEmail } = require(&aposvalidator&apos)
isEmail یک تابع اعتبار سنجی است که اگر رشته داده شده یک ایمیل باشد، مقدار true را برمی گرداند. برای اعمال اعتبار مانگوس در مدل کاربری خود به آن نیاز دارید.
سپس کد زیر را به فایل userModel خود اضافه کنید:
// models/userModel
const userSchema = mongoose.Schema({
email: {
type: String,
required: [true, &aposEmail is required&apos],
validate: {
validator: isEmail,
message: props => `${props.value} is not a valid email`
}
},
password: {
type: String,
required: [true, &aposPassword is required&apos],
validate: {
validator: function (value) {
return value.length >= 6
},
message: () => &aposPassword must be at least six characters long&apos
}
}
})
module.exports = mongoose.model(&aposUser&apos, userSchema)
کد بالا یک متغیر userSchema ایجاد می کند که مقدار متد mongoose.Schema را ذخیره می کند. روش mongoose.Schema ویژگی ها را به یک مجموعه MongoDB نگاشت می کند و شکل اسناد را در آن تعریف می کند. طرح مانگوس دارای دو ویژگی است – یک ایمیل و یک رمز عبور – که الزامات احراز هویت شما خواهند بود.
ویژگی ایمیل از نوع رشته ای است و باید مقدار درستی تنظیم شود. اگر بدنه درخواست حاوی خاصیت ایمیل نباشد، پیام خطای همراه، “ایمیل مورد نیاز است” نمایش داده می شود. در نهایت، با استفاده از اعتبارسنجی سفارشی mongoose، ویژگی اعتبار سنجی تابع isEmail را ارجاع می دهد. این تابع بر اساس اعتبار رشته به عنوان ایمیل، true یا false را برمی گرداند. سپس ویژگی message مقدار ایمیل (props) را می گیرد و یک پیام خطای معنی دار می سازد.
ویژگی رمز عبور یک نوع رشته مورد نیاز با یک پیام خطایی است که به عنوان خوانده شده “گذرواژه مورد نیاز است”. تابع اعتبار سنج یک تابع مزاحم است که اگر رمز عبور حداقل شش کاراکتر باشد، مقدار true را برمی گرداند.
خط نهایی با فراخوانی روش مدل در mongoose یک مدل mongoose ایجاد و صادر می کند. نام مدل (User) را به عنوان آرگومان اول و یک طرحواره (userSchema) را به عنوان آرگومان دوم ارسال کنید.
مرحله 4: پیاده سازی مسیرهای ورود و ثبت نام
در فهرست اصلی پروژه خود، یک پوشه routes ایجاد کنید:
mkdir routes
در پوشه routes خود، یک فایل userRoutes.js ایجاد کنید و واردهای زیر را اضافه کنید:
// routes/userRoutes.js
const express = require("express");
const User = require("../models/userModel");
const bcrypt = require("bcrypt");
با فراخوانی متد روتر در express یک نمونه روتر Express ایجاد کنید:
const router = express.Router();
سپس، مسیر ثبت نام خود را با افزودن بلوک کد زیر به فایل userRoute.js خود ایجاد کنید:
router.post("/sign-up", async (req, res) => {
try {
// Extract email and password from the req.body object
const { email, password } = req.body;
// Check if the email is already in use
let userExists = await User.findOne({ email });
if (userExists) {
res.status(401).json({ message: "Email is already in use." });
return;
}
// Define salt rounds
const saltRounds = 10;
// Hash password
bcrypt.hash(password, saltRounds, (err, hash) => {
if (err) throw new Error("Internal Server Error");
// Create a new user
let user = new User({
email,
password: hash,
});
// Save user to database
user.save().then(() => {
res.json({ message: "User created successfully", user });
});
});
} catch (err) {
return res.status(401).send(err.message);
}
});
در بلوک کد بالا، ابتدا ساختار ایمیل و رمز عبور را از شی req.body حذف کردید. سپس، بررسی کنید که آیا کاربر در حال حاضر از ایمیل استفاده می کند زیرا باید برای هر کاربر منحصر به فرد باشد. اگر ایمیل قبلاً استفاده شده باشد، اجرای کد را با کد وضعیت 401 برمی گردانید و متوقف می کنید.
ذخیره رمزهای عبور ساده در پایگاه داده یک تهدید امنیتی بزرگ است زیرا هکرهای مخرب ممکن است به پایگاه داده دسترسی پیدا کنند. شما باید رمزهای عبور را قبل از جمع کردن آنها در پایگاه داده خود هش کنید، بنابراین حتی اگر یک هکر آنها را کشف کند، نباید خطری برای کاربران وجود داشته باشد. هش کردن فرآیند تبدیل یک “کلید” داده شده به مقدار دیگر است. هش کردن یک تابع یک طرفه است، به این معنی که برخلاف رمزگذاری نمیتوانید مقدار اصلی را از hased بازیابی کنید.
با استفاده از bcrypt، رمز عبور کاربری خود را با فراخوانی روش هش در bcrypt هش کردید. متد هش سه پارامتر دارد: رشته ای که باید هش شود، salt rounds و تابع callback. رمز عبور کاربر، متغیر saltRounds را که قبلاً ایجاد کردهاید، و یک callback ارسال میکنید.
دور نمک به زمان مورد نیاز برای محاسبه یک هش bcrypt منفرد اشاره دارد. هر چه دور نمک بیشتر باشد، دور هش بیشتر است.
اگر روش هش یک خطا ایجاد کند، شما یک “خطای سرور داخلی” را پرتاب می کنید. در غیر این صورت، ویژگی رمز عبور را روی هش موفق تنظیم می کنید و با فراخوانی متد ذخیره در نمونه کاربر، آن را در پایگاه داده خود ذخیره می کنید.
سپس، مسیر ورود خود را با افزودن بلوک کد زیر به فایل userRoute.js خود ایجاد کنید:
router.post("/sign-in", async (req, res) => {
try {
// Extract email and password from the req.body object
const { email, password } = req.body;
// Check if user exists in database
let user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ message: "Invalid Credentials" });
}
// Compare passwords
bcrypt.compare(password, user.password, (err, result) => {
if (result) {
return res.status(200).json({ message: "User Logged in Successfully" });
}
console.log(err);
return res.status(401).json({ message: "Invalid Credentials" });
});
} catch (error) {
res.status(401).send(err.message);
}
});
module.exports = router;
در بلوک کد بالا، ابتدا ایمیل و رمز عبور را از شی req.body حذف می کنید. سپس، بررسی می کنید که آیا کاربر در پایگاه داده شما وجود دارد یا خیر. اگر کاربر در پایگاه داده شما وجود نداشته باشد، با یک کد وضعیت 401 برمی گردید.
در مرحله بعد، با استفاده از روش مقایسه bcrypt، رمز عبوری که کاربر ارائه کرده و رمز عبور هش شده ای را که از پایگاه داده خود بازیابی کرده اید، وارد کنید. این دو را با هم مقایسه کنید تا مطمئن شوید که مطابقت دارند یا خیر. اگر رمزهای عبور مطابقت داشته باشند، یک کد وضعیت 200 و یک پیام موفقیت آمیز را برمی گردانید. در غیر این صورت یک کد وضعیت 401 و یک پیام خطا برمی گردانید.
در نهایت، روتر را به فایل app.js خود وارد کنید و از آن به عنوان میان افزار در سطح برنامه استفاده کنید.
این مدل احراز هویت کاربر شما را کامل می کند. اکنون، کاربران می توانند به طور ایمن ثبت نام کرده و به برنامه شما وارد شوند.
اهمیت احراز هویت کاربر
احراز هویت کاربر تضمین می کند که فقط کاربران قانونی می توانند به برنامه شما دسترسی پیدا کنند. اگر دادههای شما به هر نحوی شخصی یا خصوصی هستند، باید اقداماتی را برای جلوگیری از دسترسی کاربران غیرقانونی انجام دهید.