NestJS, прогрессивный фреймворк для построения эффективных и масштабируемых серверных приложений на Node.js, предоставляет разработчикам мощный инструментарий. Однако, как и любая технология, он требует осознанного подхода к безопасности, чтобы создаваемые API и микросервисы могли противостоять современным угрозам. Безопасность в NestJS — это не отдельный модуль, а архитектурный принцип, который должен быть заложен на всех уровнях приложения. Данная инструкция проведет вас через ключевые шаги по защите вашего NestJS-приложения, сопровождая каждый этап практическими примерами кода.
Шаг 1: Валидация и санация входящих данных. Первая линия обороны — это гарантия того, что данные, поступающие в ваше приложение, корректны и безопасны. NestJS тесно интегрирован с библиотеками class-validator и class-transformer. Создавайте Data Transfer Objects (DTO) с использованием декораторов валидации.
Пример:
```
import { IsString, IsEmail, MinLength, IsNotEmpty } from 'class-validator';
export class CreateUserDto {
@IsNotEmpty()
@IsString()
username: string;
@IsEmail()
email: string;
@MinLength(8)
password: string;
}
```
В вашем контроллере используйте `ValidationPipe` с опцией `whitelist: true`, которая автоматически удалит любые свойства, не описанные в DTO, предотвращая атаки на переполнение полей.
```
@Post('users')
@UsePipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
async create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
```
Шаг 2: Аутентификация и авторизация. Для аутентификации стандартным выбором является Passport.js. Установите пакеты `@nestjs/passport`, `passport`, `passport-jwt` (или `passport-local`) и `@nestjs/jwt`.
Пример стратегии JWT:
```
// jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.JWT_SECRET, // Секрет из переменных окружения!
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
```
Для авторизации используйте Guards. Создайте ролевой Guard:
```
// roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.get('roles', context.getHandler());
if (!requiredRoles) return true;
const request = context.switchToHttp().getRequest();
const user = request.user;
return requiredRoles.some((role) => user.roles?.includes(role));
}
}
```
И применяйте его с помощью декоратора `@SetMetadata` или кастомного декоратора `@Roles(['admin'])`.
Шаг 3: Защита от веб-уязвимостей. Установите и настройте helmet для защиты заголовков HTTP:
```
import * as helmet from 'helmet';
// В файле main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(helmet());
// ... остальная конфигурация
}
```
Для защиты от CSRF-атак используйте пакет `csurf` (хотя для API, использующих токены, это часто избыточно). Защита от NoSQL-инъекций (при использовании MongoDB) обеспечивается корректным использованием ORM/ODM, такого как Mongoose, и санацией запросов.
Шаг 4: Безопасная работа с зависимостями. Регулярно обновляйте все зависимости, используя `npm audit` или `yarn audit`. Интегрируйте проверку уязвимостей в CI/CD пайплайн. Рассмотрите возможность использования Snyk или Dependabot для автоматического создания pull request с обновлениями безопасности.
Шаг 5: Логирование и мониторинг. Внедрите структурированное логирование (например, с помощью Winston или Pino) для отслеживания подозрительной активности: неудачные попытки входа, частые ошибки валидации. Настройте оповещения на большое количество 4xx/5xx ошибок с одного IP-адреса.
Шаг 6: Конфигурация и секреты. Никогда не хардкодите секреты (ключи JWT, строки подключения к БД). Используйте модуль `@nestjs/config` для работы с переменными окружения через `.env` файлы, которые добавлены в `.gitignore`.
```
// app.module.ts
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: `.env.${process.env.NODE_ENV}`,
}),
],
})
export class AppModule {}
```
Шаг 7: Ограничение частоты запросов (Rate Limiting). Защитите свои эндпоинты от брутфорса и DDoS-атак с помощью `@nestjs/throttler`.
```
// app.module.ts
import { ThrottlerModule } from '@nestjs/throttler';
@Module({
imports: [
ThrottlerModule.forRoot({
ttl: 60, // время жизни
limit: 10, // максимальное количество запросов за TTL
}),
],
})
export class AppModule {}
```
Затем используйте `@Throttle()` декоратор на контроллерах или отдельных маршрутах.
Заключительный шаг — это тестирование безопасности. Проводите регулярные аудиты кода, используйте статические анализаторы (SAST), а для критичных приложений — динамический анализ (DAST) и пентесты. Комбинация встроенных средств NestJS, сторонних библиотек и продуманной архитектуры создает надежную основу для безопасного backend-приложения.
Полное руководство по безопасности NestJS: от основ до продвинутых практик с примерами кода
Пошаговая инструкция по реализации мер безопасности в приложениях на NestJS. Включает примеры кода для валидации, JWT-аутентификации, авторизации, защиты заголовков, rate limiting и работы с конфигурацией.
144
2
Комментарии (11)