← Назад к вопросам

Какие знаешь практики обеспечения безопасности на проекте?

2.3 Middle🔥 121 комментариев
#Безопасность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Практики обеспечения безопасности в проектах Node.js

Безопасность — это многоуровневый процесс. Рассмотрю основные практики на разных уровнях.

1. Аутентификация и авторизация

JWT токены с безопасным хранением:

const jwt = require('jsonwebtoken');

function generateAccessToken(userId) {
  return jwt.sign(
    { userId, role: 'user' },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );
}

function generateRefreshToken(userId) {
  return jwt.sign(
    { userId, tokenVersion: 1 },
    process.env.REFRESH_SECRET,
    { expiresIn: '7d' }
  );
}

res.cookie('refreshToken', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 7 * 24 * 60 * 60 * 1000
});

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

function authorize(...requiredRoles) {
  return (req, res, next) => {
    const user = req.user;
    if (!user || !requiredRoles.includes(user.role)) {
      return res.status(403).json({ error: 'Forbidden' });
    }
    next();
  };
}

app.delete('/api/users/:id', authenticate, authorize('admin'), async (req, res) => {
  // Только админы могут удалять
});

2. Защита от SQL инъекций

Параметризованные запросы:

const query = 'SELECT * FROM users WHERE id = $1';
await pool.query(query, [id]);

ORM с автоматической защитой:

const user = await User.findOne({ where: { id } });
await pool.query(
  'INSERT INTO users (name, email) VALUES ($1, $2)',
  [name, email]
);

3. Защита от XSS

Санитизация пользовательского ввода:

const DOMPurify = require('isomorphic-dompurify');

const userInput = req.body.comment;
const clean = DOMPurify.sanitize(userInput);
await db.saveComment(clean);

Content Security Policy:

app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self'"
  );
  next();
});

4. Защита от CSRF

CSRF tokens:

const csrf = require('csurf');

app.use(csrf({ cookie: true }));

app.post('/api/update', csrf(), (req, res) => {
  res.json({ success: true });
});

SameSite Cookies:

res.cookie('sessionId', token, {
  sameSite: 'strict',
  secure: true,
  httpOnly: true
});

5. Защита от Brute Force

Rate limiting:

const rateLimit = require('express-rate-limit');

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  message: 'Слишком много попыток входа'
});

app.post('/api/login', loginLimiter, async (req, res) => {
  // Обработка логина
});

Экспоненциальная задержка:

async function attemptLogin(email, password) {
  const attempts = await db.getFailedAttempts(email);
  
  if (attempts >= 3) {
    const delay = Math.pow(2, Math.min(attempts - 3, 5));
    throw new Error(`Account locked for ${delay} seconds`);
  }
  
  const user = await authenticateUser(email, password);
  if (!user) {
    await db.recordFailedAttempt(email);
    throw new Error('Invalid credentials');
  }
  
  await db.clearFailedAttempts(email);
  return user;
}

6. Управление секретами

Environment variables:

const secret = process.env.JWT_SECRET;
if (!secret) {
  throw new Error('JWT_SECRET not set');
}

Secrets Manager:

const SecretsManager = require('aws-sdk/clients/secretsmanager');

async function getSecret(secretName) {
  const client = new SecretsManager({ region: 'us-east-1' });
  const data = await client.getSecretValue({ SecretId: secretName }).promise();
  return JSON.parse(data.SecretString);
}

7. Валидация данных

Schema validation:

const Joi = require('joi');

const userSchema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(8).required(),
  age: Joi.number().integer().min(18).max(120)
});

app.post('/api/register', (req, res) => {
  const { error, value } = userSchema.validate(req.body);
  if (error) {
    return res.status(400).json({ error: error.details[0].message });
  }
});

8. Логирование и мониторинг

Безопасное логирование:

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' })
  ]
});

logger.info('User login', { userId, email, ip: req.ip });
logger.error('Login failed', { email, reason: 'invalid' });

Мониторинг anomalies:

async function monitorLogin(email, ip) {
  const recentLogins = await db.getRecentLogins(email, '24h');
  const ips = new Set(recentLogins.map(l => l.ip));
  
  if (recentLogins.length > 10 || ips.size > 5) {
    await sendSecurityAlert(email, 'Unusual login activity');
  }
}

9. HTTPS и TLS

Обязательный HTTPS:

app.use((req, res, next) => {
  if (!req.secure && process.env.NODE_ENV === 'production') {
    return res.redirect(`https://${req.headers.host}${req.url}`);
  }
  next();
});

res.setHeader('Strict-Transport-Security', 'max-age=31536000');

10. Dependency management

Проверяем и обновляем:

npm audit
npm update
npm ci

Чеклист безопасности

  • JWT с коротким сроком действия
  • Refresh tokens в HttpOnly cookies
  • Параметризованные SQL запросы
  • Санитизация пользовательского ввода
  • CSRF protection включена
  • Rate limiting на критичных операциях
  • Секреты в environment variables
  • HTTPS в production
  • CSP заголовки установлены
  • Логирование без чувствительных данных
  • Регулярные обновления зависимостей
  • Двухфакторная аутентификация для админов

Безопасность — это постоянный процесс контроля и улучшения, а не одноразовая настройка.