Приклад сервісу для ідентифікації користувачів
Коли ви створюєте систему, що вимагає ідентифікації користувачів у внутрішній функції, розгляньте наступний приклад сервісу (за умови, що модуль ресурсу вже створено):
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository,
) {}
async getUser(userId: string) {
return this.userRepository.findOne({ where: { id: userId } }); // Знайти одного користувача.
}
}
Додавання аутентифікації
Тепер уявімо, що вам потрібно аутентифікувати внутрішній сервіс для перевірки чогось за допомогою bearerToken
, що передається в заголовку запиту. Зазвичай для цього використовують токен як параметр:
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository,
) {}
async getUser(userId: string, bearerToken: string) {
const user = await this.userRepository.findOne({ where: { id: userId } });
const isValid = someFunc(bearerToken); // Перевірка токена.
return { user, isValid };
}
}
Однак передача bearerToken
як параметра може бути не завжди ідеальною, оскільки це не безпосередньо пов'язано з логікою getUser
.
Рішення за допомогою AsyncLocalStorage
Замість того, щоб передавати токен як параметр, ви можете зберігати його за допомогою AsyncLocalStorage, що надається NestJS, і отримувати його в будь-якому місці вашого коду. Пакет nestjs-cls
спрощує цей процес.
Налаштування nestjs-cls
Встановіть пакет:
npm install nestjs-cls
Потім налаштуйте його в AppModule
, щоб увімкнути ClsMiddleware
глобально:
import { Module } from '@nestjs/common';
import { ClsModule } from 'nestjs-cls';
import { UserService } from './user.service';
import { UserController } from './user.controller';
@Module({
imports: [
ClsModule.forRoot({
middleware: {
// Автоматичне підключення middleware для всіх маршрутів
mount: true,
setup: (cls, req) => {
// Зберігайте токен аутентифікації з заголовка в AsyncLocalStorage
cls.set('userToken', req.headers['x-user-token']);
},
},
}),
],
providers: [UserService],
controllers: [UserController],
})
export class AppModule {}
Використання ClsService
в Сервісі
Тепер ви можете безпосередньо отримати доступ до AsyncLocalStorage
у UserService
:
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { ClsService } from 'nestjs-cls';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository,
private readonly cls: ClsService, // Впроваджуємо ClsService
) {}
async getUser(userId: string) {
const user = await this.userRepository.findOne({ where: { id: userId } });
// Отримуємо токен, збережений в AsyncLocalStorage
const bearerToken = this.cls.get('userToken');
const isValid = someFunc(bearerToken); // Перевіряємо токен
return { user, isValid };
}
}
Переваги nestjs-cls
- Уникає передачі зайвих параметрів: Отримуйте доступ до контекстних даних, таких як токени, в будь-якому місці виконання.
- Легкість налаштування: Middleware автоматично обробляє конфігурацію.
- Безшовна інтеграція з NestJS: Спрощує реалізацію за допомогою вбудованих інструментів фреймворку.
Посилання
офіційна документація AsyncLocalStorage для NestJS
Перекладено з: Accessing Local Storage in NestJS