1. Helmet — Security Headers
npm install helmet
// main.ts
import helmet from 'helmet';
const app = await NestFactory.create(AppModule);
app.use(helmet());
// Tự động thêm headers:
// X-Content-Type-Options: nosniff
// X-Frame-Options: SAMEORIGIN
// X-XSS-Protection: 0
// Strict-Transport-Security: max-age=15552000
// Content-Security-Policy: default-src 'self'
2. CORS Configuration
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: [
'https://myapp.com',
'https://admin.myapp.com',
],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 3600,
});
3. Rate Limiting với @nestjs/throttler
npm install @nestjs/throttler
// app.module.ts
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
@Module({
imports: [
ThrottlerModule.forRoot([
{ name: 'short', ttl: 1000, limit: 3 }, // 3 req/giây
{ name: 'medium', ttl: 10000, limit: 20 }, // 20 req/10 giây
{ name: 'long', ttl: 60000, limit: 100 }, // 100 req/phút
]),
],
providers: [
{ provide: APP_GUARD, useClass: ThrottlerGuard }, // Global
],
})
export class AppModule {}
// Custom limits per route
@Throttle([{ name: 'short', ttl: 1000, limit: 1 }]) // 1 req/giây
@Post('login')
login() { ... }
// Skip throttling
@SkipThrottle()
@Get('health')
health() { return 'OK'; }
4. Environment Variables với @nestjs/config
npm install @nestjs/config joi
// app.module.ts
import { ConfigModule, ConfigService } from '@nestjs/config';
import * as Joi from 'joi';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: `.env.${process.env.NODE_ENV || 'development'}`,
validationSchema: Joi.object({
NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
PORT: Joi.number().default(3000),
DATABASE_URL: Joi.string().required(),
JWT_ACCESS_SECRET: Joi.string().required().min(32),
JWT_REFRESH_SECRET: Joi.string().required().min(32),
REDIS_URL: Joi.string().optional(),
}),
}),
],
})
export class AppModule {}
// Sử dụng
@Injectable()
export class AuthService {
constructor(private config: ConfigService) {}
getJwtSecret(): string {
return this.config.get<string>('JWT_ACCESS_SECRET');
}
}
5. Input Sanitization
// Dùng class-transformer để sanitize
import { Transform } from 'class-transformer';
export class CreateCommentDto {
@IsString()
@Transform(({ value }) => value.replace(/<[^>]*>/g, '')) // Strip HTML tags
content: string;
@IsString()
@Transform(({ value }) => value.trim().toLowerCase())
email: string;
}
// Hoặc dùng DOMPurify/sanitize-html cho HTML content
import sanitizeHtml from 'sanitize-html';
@Transform(({ value }) => sanitizeHtml(value, {
allowedTags: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
allowedAttributes: { a: ['href'] },
}))
htmlContent: string;
6. Phòng chống SQL Injection
// ✅ Đúng — Parameterized queries (TypeORM)
const users = await repo.createQueryBuilder('user')
.where('user.email = :email', { email: userInput })
.getMany();
// ✅ Đúng — Prisma (tự động parameterized)
const users = await prisma.user.findMany({
where: { email: userInput },
});
// ❌ SAI — String concatenation
const users = await repo.query(`SELECT * FROM users WHERE email = '${userInput}'`);
7. Các Best Practices khác
// 1. Compression
import compression from 'compression';
app.use(compression());
// 2. Request size limit
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ limit: '10mb', extended: true }));
// 3. Logging — không log sensitive data
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
const req = context.switchToHttp().getRequest();
const { password, token, ...safeBody } = req.body;
console.log(`${req.method} ${req.url}`, safeBody);
return next.handle();
}
}
// 4. Graceful shutdown
app.enableShutdownHooks();
8. Tổng kết
| Mối đe dọa | Giải pháp |
|---|---|
| XSS | Helmet, Input sanitization, CSP headers |
| SQL Injection | Parameterized queries (TypeORM/Prisma) |
| Brute Force | Rate Limiting (@nestjs/throttler) |
| CSRF | SameSite cookies, CSRF tokens |
| Sensitive Data | @nestjs/config, .env files, không log passwords |
| Clickjacking | X-Frame-Options via Helmet |
| CORS | Whitelist origins |
Bài tiếp theo sẽ tìm hiểu Session, Cookies và OAuth2.