Используйте структурированную архитектуру Nest для создания безопасных и эффективных REST API.
Express.js — отличная технология для создания безопасных и надежных REST API, однако она не предоставляет предопределенной структуры. Его минималистичный характер позволяет вам обрабатывать важные аспекты, такие как маршрутизация, организация кода и меры безопасности, либо вручную, либо с использованием доступного промежуточного программного обеспечения и библиотек.
Напротив, Nest.js, построенный поверх Express.js и Node.js, вводит абстракцию более высокого уровня. который предлагает четкую структуру, надежный подход к организации кода и упрощенную реализацию подробности. По сути, Nest.js предоставляет более структурированную архитектуру для создания эффективных и безопасных серверных API и сервисов.
Настройка проекта Nest.js
Чтобы начать работу, вам сначала необходимо установить командную строку Nest.js (CLI) глобально, выполнив следующую команду:
npm i -g @nestjs/cli
После завершения установки создайте новый проект, запустив:
гнездо новое гнездо-jwt-api
Затем интерфейс командной строки Nest.js предложит вам выбрать менеджер пакетов для установки зависимостей. Для этого урока мы будем использовать npm, диспетчер пакетов узлов. Выбирать нпм и подождите, пока интерфейс командной строки создаст базовый проект Nest.js и установит все необходимые файлы конфигурации и исходные зависимости, необходимые для запуска приложения.
После настройки проекта перейдите в каталог проекта и запустите сервер разработки.
cd гнездо-jwt-api
запуск запуска нпм
Наконец, запустите команду ниже, чтобы установить пакеты, которые мы будем использовать для этого проекта.
npm установить mongodb mongoose @nestjs/mongoose @types/bcrypt bcrypt jsonwebtoken @nestjs/jwt
Вы можете найти код этого проекта в этом Репозиторий GitHub.
Настройка подключения к базе данных MongoDB
Настройте базу данных MongoDB локально или настроить кластер MongoDB в облаке. После настройки базы данных скопируйте строку URI подключения к базе данных, создайте .env файл в корневом каталоге папки нашего проекта и вставьте в строку подключения:
MONGO_URI="строка подключения"
Далее обновите app.module.ts в источник файл каталога для настройки Mongoose следующим образом:
Импортировать {Модуль} от'@nestjs/общий';
Импортировать {Модуль конфигурации} от'@nestjs/config';
Импортировать {Модуль мангуста} от'@nestjs/мангуст';
Импортировать {Контроллер приложений} от'./приложение.контроллер';
Импортировать { Служба приложений } от'./приложение.сервис';
Импортировать {УсерАусМодуле} от'./user-auth/user-auth.module';@Модуль({
импорт: [
ConfigModule.forRoot({
envFilePath: '.env',
глобальный: истинный,
}),
MongooseModule.forRoot(process.env. МОНГО_URI),
UserAuthModule,
],
контроллеры: [AppController],
провайдеры: [AppService],
})
экспортсорт AppModule {}
Предоставленный код настраивает три основных модуля для приложения Nest.js: Конфигурационный модуль для конфигурации среды, МангустМодуль для установления соединения с MongoDB и UserAuthModule для аутентификации пользователя. Обратите внимание, что на этом этапе может возникнуть ошибка, т.к. UserAuthModule еще не определен, но мы создадим его в следующем разделе.
Создание модуля аутентификации пользователя
Чтобы поддерживать чистый и хорошо организованный код, создайте модуль проверки подлинности пользователя, выполнив следующую команду.
аутентификация пользователя в модуле g
Инструмент Nest.js CLI автоматически создает необходимые файлы модулей. Кроме того, он обновит app.module.ts файл, включающий необходимые изменения, связанные с модулем аутентификации пользователя.
Вы можете создать основные файлы конфигурации проекта вручную, тем не менее, инструмент CLI упрощает этот процесс путем автоматического создания необходимых элементов, а также соответствующего обновления изменений в в app.module.ts файл.
Создайте схему пользователя
Внутри только что созданного авторизация пользователя папка в источник каталог, создайте новый схемы/user-auth.schema.ts файл и добавьте следующий код, чтобы создать схему Mongoose для Пользователь модель
Импортировать { Опора, схема, фабрика схем} от'@nestjs/мангуст';
Импортировать {Документ} от'мангуста';@Схема({ временные метки: истинный })
экспортсорт Пользователь {
@Prop()
имя пользователя: нить;
@Prop()
пароль: нить;
}
экспорттип UserDocument = Пользователь и документ;
экспортконстанта UserSchema = SchemaFactory.createForClass (Пользователь);
Создание службы аутентификации пользователей
Теперь давайте создадим службу аутентификации пользователей, которая будет управлять логикой аутентификации для REST API, выполнив следующую команду:
аутентификация пользователя службы Nest G
Эта команда создаст пользователь-auth.service.ts файл внутри каталога user-auth. Откройте этот файл и обновите его следующим кодом.
- Сначала сделайте следующий импорт.
Импортировать { Injectable, NotFoundException, Logger, UnauthorizedException } от'@nestjs/общий';
Импортировать {ИнжектМодель} от'@nestjs/мангуст';
Импортировать {Модель} от'мангуста';
Импортировать { Пользователь } от'./schemas/user-auth.schema';
Импортировать * как bcrypt от'bcrypt';
Импортировать {ДжвтСервис} от'@nestjs/jwt'; - Затем создайте UserAuthService класс, который инкапсулирует функциональность для регистрации пользователей, входа в систему и получения всех маршрутов пользовательских данных.
@Инъекционный()
экспортсорт UserAuthService {
частный регистратор только для чтения = новый Регистратор (UserAuthService.name);
конструктор(@InjectModel(Имя пользователя) частный модель пользователя: Модель, частный jwtService: JwtService ) {}
асинхронный registerUser (имя пользователя: нить, пароль: нить): Обещатьнить }> {
пытаться {
константа хэш = Ждите bcrypt.hash (пароль, 10);
Ждитеэтот.userModel.create({имя пользователя, пароль: хеш});
возвращаться { сообщение: «Пользователь успешно зарегистрирован» };
} ловить (ошибка) {
бросатьновыйОшибка("Произошла ошибка при регистрации пользователя");
}
}асинхронный loginUser (имя пользователя: нить, пароль: нить): Обещать<нить> {
пытаться {
константа пользователь = Ждитеэтот.userModel.findOne({имя пользователя});
если (!пользователь) {
бросатьновый NotFoundException('Пользователь не найден');
}
константа парольMatch = Ждите bcrypt.compare(пароль, user.password);
если (!Соответствие паролю) {
бросатьновый Несанкционированное исключение ('Неверные логин или пароль');
}
константа полезная нагрузка = {userId: user._id};
константа жетон = этот.jwtService.sign (полезная нагрузка);
возвращаться жетон;
} ловить (ошибка) {
консоль.лог (ошибка);
бросатьновый Несанкционированное исключение («Произошла ошибка при входе в систему»);
}
}
асинхронный получитьпользователей(): Обещать
{
пытаться {
константа пользователи = Ждитеэтот.userModel.find({});
возвращаться пользователи;
} ловить (ошибка) {
этот.logger.ошибка(`Произошла ошибка при получении пользователей: ${ошибка.сообщение}`);
бросатьновыйОшибка("Произошла ошибка при получении пользователей");
}
}
}
UserAuthService Класс реализует логику регистрации пользователя, входа в систему и получения пользовательских данных. Он использует модель пользователя для взаимодействия с базой данных и выполнения необходимых действий, включая хеширование пароля во время регистрация, проверка учетных данных для входа и, наконец, создание токенов JWT после успешного аутентификация.
Внедрение защиты аутентификации
Для обеспечения безопасности конфиденциальных ресурсов крайне важно ограничить доступ исключительно авторизованным пользователям. Это достигается за счет применения меры безопасности, которая требует наличия действительного JWT в последующих запросах API, направляемых к защищенным конечным точкам, в данном случае пользователи маршрут. в авторизация пользователя каталог, создайте новый auth.guard.ts файл и добавьте код ниже.
Импортировать { CanActivate, ExecutionContext, Injectable, UnauthorizedException } от'@nestjs/общий';
Импортировать {ДжвтСервис} от'@nestjs/jwt';
Импортировать { Запрос } от'выражать';
Импортировать { Секретный ключ } от'./конфигурация';@Инъекционный()
экспортсорт AuthGuard реализует CanActivate {
конструктор(частный jwtService: JwtService) {}
асинхронный canActivate (контекст: ExecutionContext): Обещать<логический> {
константа запрос = context.switchToHttp().getRequest();
константа жетон = этот.extractTokenFromHeader (запрос);
если (! токен) {
бросатьновый Несанкционированное исключение();
}
пытаться {
константа полезная нагрузка = Ждитеэтот.jwtService.verifyAsync (токен, {
секрет: секретКей.секрет,
});
запрос['пользователь'] = полезная нагрузка;
} ловить {
бросатьновый Несанкционированное исключение();
}
возвращатьсяистинный;
}
частный ExtractTokenFromHeader (запрос: запрос): нить | неопределенный {
константа [тип, токен] = request.headers.authorization?.split(' ')?? [];
возвращатьсятип«Носитель»? токен: неопределенный;
}
}
Код реализует сторожить, как указано в официальной документации, для защиты маршрутов и обеспечения доступа к ним только аутентифицированных пользователей с действительным токеном JWT.
Он извлекает токен JWT из заголовка запроса, проверяет его подлинность с помощью джвтсервис, и присваивает декодированную полезную нагрузку запрос['пользователь'] имущества для дальнейшей обработки. Если токен отсутствует или недействителен, выдается Неавторизованное исключение для предотвращения доступа к защищенному маршруту.
Теперь создайте config.ts файл в том же каталоге и добавьте приведенный ниже код.
экспортконстанта секретный ключ = {
секрет: «СЕКРЕТНАЯ ЦЕННОСТЬ».,
};
Этот секретный ключ используется для подписи и проверки подлинности JWT. Важно надежно хранить значение ключа, чтобы предотвратить несанкционированный доступ и защитить целостность JWT.
Определить контроллер API
Создайте контроллер, который обрабатывает конечные точки API для аутентификации пользователей.
аутентификация пользователя контроллера Nest G
Затем скопируйте код, указанный в этом Файл репозитория GitHub, и добавьте его в пользователь-auth.controller.ts файл — он определяет конечные точки для регистрации пользователей, входа в систему и получения пользовательских данных. Усегардс (AuthGuard) декоратор включен для обеспечения аутентификации для получитьпользователей конечной точки, гарантируя, что доступ предоставляется только пользователям, прошедшим проверку подлинности.
Обновите файл user-auth.module.ts
Чтобы отразить изменения, внесенные в проект, обновите пользователь-auth.module.ts файл для настройки необходимых модулей, служб и контроллеров для аутентификации пользователей.
Импортировать {Модуль, NestModule, MiddlewareConsumer} от'@nestjs/общий';
Импортировать {JwtModule} от'@nestjs/jwt';
Импортировать {Усераусконтроллер} от'./user-auth.controller';
Импортировать {УсерАусСервис} от'./user-auth.service';
Импортировать {Модуль мангуста} от'@nestjs/мангуст';
Импортировать { Пользовательская схема } от'./schemas/user-auth.schema';
Импортировать { Секретный ключ } от'./конфигурация';@Модуль({
импорт: [
MongooseModule.forFeature([{имя: 'Пользователь', схема: UserSchema }]),
JwtModule.register({
секрет: секретКей.секрет,
signOptions: { expiresIn: '1ч' },
}),
],
контроллеры: [UserAuthController],
провайдеры: [UserAuthService],
})
экспортсорт UserAuthModule реализует NestModule {
настроить (потребитель: MiddlewareConsumer) {
}
}
Наконец, запустите сервер разработки и протестируйте конечные точки API с помощью Postman.
запуск запуска нпм
Создание безопасных REST API Nest.js
Создание безопасных REST API Nest.js требует комплексного подхода, выходящего за рамки простого использования JWT для аутентификации и авторизации. Хотя JWT важны, не менее важно реализовать дополнительные меры безопасности.
Кроме того, отдавая приоритет безопасности на каждом этапе разработки API, вы можете обеспечить безопасность своих серверных систем.