امنیت در برنامه های Node.js
با گسترش استفاده از Node.js در پروژههای وب و سرویسهای میکروسرویسی، مباحث امنیتی اهمیت زیادی پیدا کردهاند. این مقاله به طور جامع و کاربردی نکات کلیدی و تکنیکهای محافظتی برای افزایش امنیت برنامههای Node.js را پوشش میدهد؛ از تنظیمات سرور و مدیریت وابستگیها گرفته تا محافظت از احراز هویت و جلوگیری از حملات معمول.
تهدیدهای رایج در برنامههای Node.js
- تزریق (SQL/NoSQL Injection)
- Cross-Site Scripting (XSS) و Cross-Site Request Forgery (CSRF)
- لو رفتن توکنها یا کلیدها (Secrets Leakage)
- حملات DOS/Brute Force
- وابستگیهای آسیبپذیر در npm
- Session hijacking و سوءاستفاده از کوکیها
اصول اولیه امنیت و پیکربندی سرور
قبل از هر چیز باید محیط اجرا (runtime) و زیرساخت را امن کنید: از HTTPS استفاده کنید، TLS را درست پیکربندی کنید، پورتهای غیرضروری را ببندید و بهروزرسانیهای سیستم و کتابخانهها را مرتب اعمال کنید.
نمونه: راهاندازی HTTPS در Node.js
const fs = require('fs');
const https = require('https');
const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('Hello secure world'));
const options = {
key: fs.readFileSync('/path/to/privkey.pem'),
cert: fs.readFileSync('/path/to/fullchain.pem')
};
https.createServer(options, app).listen(443, () => {
console.log('HTTPS server running on port 443');
});توضیح: این کد یک سرور HTTPS ساده با Express ایجاد میکند. استفاده از گواهی معتبر (مثلاً از Let’s Encrypt) و خواندن فایلهای کلید/گواهی از مسیر امن ضروری است. در محیط تولید هرگز کلیدها را در مخزن گیت ذخیره نکنید؛ از secret manager یا سرویسهایی مثل AWS Secrets Manager / Azure Key Vault استفاده کنید.
محافظت لایه کاربردی: هِلمِت، CORS و هِدِرها
کتابخانه Helmet برای تنظیم هدرهای امنیتی مفید است. همچنین CORS را به دقت پیکربندی کنید تا فقط دامنههای مورد اعتماد اجازه دسترسی داشته باشند.
const helmet = require('helmet');
const cors = require('cors');
app.use(helmet());
app.use(cors({
origin: ['https://yourdomain.com'],
methods: ['GET', 'POST'],
credentials: true
}));توضیح: helmet هدرهایی مثل X-Frame-Options، X-Content-Type-Options و Content-Security-Policy را تنظیم میکند. CORS نیز دسترسی منابع را محدود میکند. توجه داشته باشید که استفاده از origin: ‘*’ همراه با credentials کار نمیکند و خطرناک است.
احراز هویت و مدیریت نشست (Sessions)
برای ذخیره نشستها از کوکیهای امن یا توکنهای کوتاهمدت استفاده کنید. در صورت استفاده از JWT، نکات زیر را رعایت کنید:
- از امضای قوی (RS256 یا HS256 با کلید قوی) استفاده کنید.
- زمان عمر (exp) کوتاه و مکان برای ریفرش توکن در نظر بگیرید.
- توکنهای حساس را در کوکیهای HttpOnly و Secure ذخیره کنید تا دسترسی جاوااسکریپت به آنها محدود شود.
const jwt = require('jsonwebtoken');
const token = jwt.sign({ userId: 123 }, process.env.JWT_SECRET, {
algorithm: 'HS256',
expiresIn: '15m'
});توضیح: ساخت JWT با کلید مخفی و زمان انقضای کوتاه. در محیط تولید از کلیدهای قوی استفاده کنید و آنها را در متغیرهای محیطی نگهدارید. برای refresh token از مکانیزم امن و با امکان لغو (revocation) استفاده کنید.
حفظ امنیت ورودیها و جلوگیری از تزریق
هر ورودی کاربر باید اعتبارسنجی و سودمندی آن کنترل شود. برای SQL از پرسوجوهای پارامتری یا ORMهای امن استفاده کنید. برای NoSQL مثل MongoDB مراقب prototype pollution و عملیاتهایی که ورودی مستقیم را اجرا میکنند باشید.
// نمونه استفاده از pg با پارامترها (Postgres)
const { Pool } = require('pg');
const pool = new Pool();
const getUserByEmail = async (email) => {
const res = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
return res.rows[0];
};توضیح: استفاده از پارامترها (در اینجا $1) جلوی SQL injection را میگیرد. هرگز ورودیها را با concat مستقیم در کوئری قرار ندهید.
رمزنگاری رمزعبورها و دادههای حساس
برای ذخیره رمزعبورها از الگوریتمهای قوی مانند bcrypt یا Argon2 استفاده کنید. هرگز از هشهای ساده یا مقایسه متنی استفاده نکنید.
const bcrypt = require('bcrypt');
async function hashPassword(plain) {
const saltRounds = 12;
const hash = await bcrypt.hash(plain, saltRounds);
return hash;
}
async function verifyPassword(plain, hash) {
return await bcrypt.compare(plain, hash);
}توضیح: bcrypt با salt داخلی کار میکند و مقدار saltRounds را متناسب با قدرت سختافزار تنظیم کنید (افزایش rounds کندتر اما امنتر است). در مقابل Argon2 عملکرد امنیتی بهتری دارد و در پروژههای جدید پیشنهاد میشود.
محافظت در برابر حملات DoS و Brute-Force
- Rate limiting برای نقاط حساس مثل login ایجاد کنید (express-rate-limit).
- Captcha برای فرمهای ورود یا ثبتنام اضافه کنید.
- مانیتورینگ و alert برای افزایش ناگهانی ترافیک تنظیم کنید.
const rateLimit = require('express-rate-limit');
app.use('/api/', rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
standardHeaders: true,
legacyHeaders: false
}));توضیح: این مثال محدودیت درخواست را در مسیرهای API اعمال میکند تا حملات تکراری کنترل شوند. برای مسیرهای حساس مانند /login تنظیمات سختگیرانهتری اعمال کنید.
مدیریت وابستگیها و اسکن آسیبپذیری
وابستگیهای npm را مرتباً با ابزارهایی مثل npm audit، Snyk یا Dependabot بررسی و بهروز کنید. در CI pipelines، اسکن خودکار آسیبپذیریها را قرار دهید و قوانین شکستخورده (fail build) در صورت وجود آسیبپذیریهای بحرانی اعمال کنید.
نمونه جدول ابزارها و کارکرد
| ابزار | کارکرد |
|---|---|
| helmet | تنظیم هدرهای امنیتی |
| express-rate-limit | محدودسازی درخواستها |
| npm audit / Snyk | اسکن وابستگیها برای آسیبپذیری |
| OWASP ZAP | اسکن امنیتی خودکار برنامه وب |
بهترین شیوههای عملی و نکات پایانی
- هرگز secrets (کلیدها، پسوردها) را در کد منبع قرار ندهید؛ از secret manager استفاده کنید.
- ورود به سیستم و لاگینگ را طوری انجام دهید که دادههای حساس لاگ نشوند.
- پالیسیهای CSP را برای جلوگیری از XSS پیاده کنید.
- دسترسی به دیتابیس و سرویسها را با حداقل امتیازات (least privilege) پیکربندی کنید.
- تست نفوذ (pentest) و اسکن امنیتی منظم را فراموش نکنید.
مثال: فعال کردن Content Security Policy با Helmet
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://trustedscripts.example.com"],
objectSrc: ["'none'"],
upgradeInsecureRequests: []
}
})
);توضیح: CSP با تعیین منابع مجاز برای اسکریپتها، استایلها و رسانهها از XSS محافظت میکند. در محیطی که از CDN استفاده میکنید، دامنههای امن را داخل policy قرار دهید و قبل از اعمال در سطح تولید، سیاست را در حالت گزارشگیری (report-only) بررسی کنید.
جمعبندی: امنیت در Node.js ترکیبی از پیکربندی درست سرور، محافظت در لایهٔ کاربرد، اعتبارسنجی ورودی، مدیریت امن توکنها و کنترل وابستگیها است. رعایت این نکات به همراه مانیتورینگ و اسکن مداوم میتواند خطرات رایج را به طور قابلتوجهی کاهش دهد.
آیا این مطلب برای شما مفید بود ؟




