Využijte strukturovanou architekturu Nest k vytvoření bezpečných a efektivních REST API.
Express.js je skvělá technologie pro vytváření bezpečných a robustních REST API, ale neposkytuje předem definovanou strukturu. Jeho minimalistická povaha vám umožňuje zvládnout základní aspekty, jako je směrování, organizace kódu a bezpečnostní opatření, buď ručně, nebo s využitím dostupného middlewaru a knihoven.
Naproti tomu Nest.js, postavený na Express.js a Node.js, zavádí abstrakci vyšší úrovně který nabízí jasnou strukturu, robustní přístup k organizaci kódu a zjednodušenou implementaci podrobnosti. Nest.js v podstatě poskytuje strukturovanější architekturu pro vytváření efektivních a bezpečných backendových API a služeb.
Nastavení projektu Nest.js
Chcete-li začít, musíte nejprve globálně nainstalovat příkazový řádek (CLI) Nest.js spuštěním příkazu níže:
npm i -g @nestjs/cli
Po dokončení instalace pokračujte a vytvořte nový projekt spuštěním:
hnízdo nové hnízdo-jwt-api
Dále vás Nest.js CLI vyzve k výběru správce balíčků k instalaci závislostí. Pro tento tutoriál použijeme
npm, Správce balíčků uzlů. Vybrat npm a počkejte, než CLI vytvoří základní projekt Nest.js a nainstaluje všechny požadované konfigurační soubory a počáteční závislosti potřebné ke spuštění aplikace.Po nastavení projektu přejděte do adresáře projektu a spusťte vývojový server.
cd nest-jwt-api
npm spuštění běhu
Nakonec spusťte níže uvedený příkaz a nainstalujte balíčky, které použijeme pro tento projekt.
npm nainstalovat mongodb mongoose @nestjs/mongoose @types/bcrypt bcrypt jsonwebtoken @nestjs/jwt
Zde najdete kód tohoto projektu úložiště GitHub.
Nakonfigurujte připojení databáze MongoDB
Lokálně nastavte databázi MongoDB nebo nakonfigurujte cluster MongoDB v cloudu. Po nastavení databáze zkopírujte řetězec URI připojení k databázi, vytvořte a .env soubor v kořenovém adresáři složky našeho projektu a vložte připojovací řetězec:
MONGO_URI="připojovací řetězec"
Dále aktualizujte app.module.ts v src adresářový soubor pro konfiguraci Mongoose následovně:
import { Modul } z'@nestjs/common';
import { ConfigModule } z'@nestjs/config';
import { MongooseModule } z'@nestjs/mongoose';
import { AppController } z'./app.controller';
import { AppService } z'./app.service';
import { UserAuthModule } z'./user-auth/user-auth.module';@Modul({
dovoz: [
ConfigModule.forRoot({
envFilePath: '.env',
isGlobal: skutečný,
}),
MongooseModule.forRoot (process.env. MONGO_URI),
UserAuthModule,
],
ovladače: [AppController],
poskytovatelé: [AppService],
})
vývoznítřída AppModule {}
Poskytnutý kód konfiguruje tři základní moduly pro aplikaci Nest.js: ConfigModule pro konfiguraci prostředí, MongooseModule pro navázání připojení MongoDB a UserAuthModule pro ověření uživatele. Upozorňujeme, že v této fázi může dojít k chybě, protože UserAuthModule ještě není definován, ale vytvoříme jej v další části.
Vytvoření modulu pro autentizaci uživatele
Chcete-li zachovat čistý a dobře organizovaný kód, vytvořte modul pro ověření uživatele spuštěním následujícího příkazu.
hnízdo g modul user-auth
Nástroj Nest.js CLI automaticky vygeneruje požadované soubory modulu. Kromě toho bude aktualizovat app.module.ts soubor obsahující nezbytné změny související s modulem autentizace uživatele.
Můžete se rozhodnout vytvořit hlavní konfigurační soubory projektu ručně, nicméně nástroj CLI zjednodušuje tento proces automatickým vytvářením požadovaných položek a odpovídající aktualizací změn v a app.module.ts soubor.
Vytvořte uživatelské schéma
Uvnitř nově vytvořeného user-auth složku v src adresář, vytvořte nový schema/user-auth.schema.ts a přidejte následující kód pro vytvoření schématu Mongoose pro Uživatel Modelka
import { Prop, Schema, SchemaFactory } z'@nestjs/mongoose';
import { Dokument } z'mangusta';@Schéma({ časových razítek: skutečný })
vývoznítřída uživatel {
@Podpěra()
uživatelské jméno: tětiva;
@Podpěra()
Heslo: tětiva;
}
vývoznítyp UserDocument = Uživatel a dokument;
vývozníkonst UserSchema = SchemaFactory.createForClass (Uživatel);
Vytvoření služby ověřování uživatelů
Nyní vytvoříme službu ověřování uživatelů, která bude spravovat logiku ověřování pro REST API spuštěním příkazu níže:
vnořovat g služby user-auth
Tento příkaz vytvoří a user-auth.service.ts soubor v adresáři user-auth. Otevřete tento soubor a aktualizujte jej pomocí následujícího kódu.
- Nejprve proveďte následující importy.
import { Injectable, NotFoundException, Logger, UnauthorizedException } z'@nestjs/common';
import { InjectModel } z'@nestjs/mongoose';
import { Modelka } z'mangusta';
import { Uživatel } z'./schemas/user-auth.schema';
import * tak jako bcrypt z'bcrypt';
import { JwtService } z'@nestjs/jwt'; - Poté vytvořte a UserAuthService třída, která zapouzdřuje funkce pro registraci uživatele, přihlášení a načítání všech tras uživatelských dat.
@Injekční()
vývoznítřída UserAuthService {
soukromé zapisovač pouze pro čtení = Nový Logger (UserAuthService.name);
konstruktér(@InjectModel(Uživatelské jméno) soukromé userModel: Model, soukromé jwtService: JwtService ) {}
asynchronní registerUser (uživatelské jméno: tětiva, Heslo: tětiva): Slibtětiva }> {
Snaž se {
konst hash = čekat bcrypt.hash (heslo, 10);
čekattento.userModel.create({ uživatelské jméno, heslo: hash });
vrátit se { zpráva: 'Uživatel byl úspěšně zaregistrován' };
} chytit (chyba) {
házetNovýChyba("Při registraci uživatele došlo k chybě");
}
}asynchronní loginUser (uživatelské jméno: tětiva, Heslo: tětiva): Slib<tětiva> {
Snaž se {
konst uživatel = čekattento.userModel.findOne({ uživatelské jméno });
-li (!user) {
házetNový NotFoundException('Uživatel nenalezen');
}
konst passwordMatch = čekat bcrypt.compare (heslo, user.password);
-li (!passwordMatch) {
házetNový UnauthorizedException('Neplatné přihlašovací údaje');
}
konst payload = { userId: user._id };
konst token = tento.jwtService.sign (užitné zatížení);
vrátit se žeton;
} chytit (chyba) {
řídicí panel.log (chyba);
házetNový UnauthorizedException("Při přihlašování došlo k chybě");
}
}
asynchronní getUsers(): Slib
{
Snaž se {
konst uživatelé = čekattento.userModel.find({});
vrátit se uživatelé;
} chytit (chyba) {
tento.logger.error(`Při načítání uživatelů došlo k chybě: ${error.message}`);
házetNovýChyba("Při načítání uživatelů došlo k chybě");
}
}
}
The UserAuthService třída implementuje logiku registrace uživatele, přihlášení a načítání uživatelských dat. Používá se uživatelský model pro interakci s databází a provádění požadovaných akcí včetně hašování hesla během registrace, ověřování přihlašovacích údajů a nakonec generování tokenů JWT po úspěšném dokončení autentizace.
Implementace Authentication Guard
Pro zajištění bezpečnosti citlivých zdrojů je klíčové omezit přístup výhradně na oprávněné uživatele. Toho je dosaženo prosazením bezpečnostního opatření, které nařizuje přítomnost platného JWT v následných požadavcích API odeslaných na chráněné koncové body, v tomto případě uživatelů trasa. V user-auth adresář, vytvořte nový auth.guard.ts soubor a přidejte kód níže.
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } z'@nestjs/common';
import { JwtService } z'@nestjs/jwt';
import { Žádost } z'vyjádřit';
import { tajný klíč } z'./config';@Injekční()
vývoznítřída AuthGuard nářadí CanActivate {
konstruktér(soukromé jwtService: JwtService) {}
asynchronní canActivate (kontext: ExecutionContext): Slib<booleovský> {
konst request = context.switchToHttp().getRequest();
konst token = tento.extractTokenFromHeader (požadavek);
-li (!token) {
házetNový UnauthorizedException();
}
Snaž se {
konst užitečné zatížení = čekattento.jwtService.verifyAsync (token, {
tajemství: secretKey.secret,
});
žádost['uživatel'] = užitečné zatížení;
} chytit {
házetNový UnauthorizedException();
}
vrátit seskutečný;
}
soukromé extractTokenFromHeader (požadavek: Požadavek): tětiva | nedefinováno {
konst [typ, token] = request.headers.authorization?.split(' ')?? [];
vrátit setyp'Nosič'? žeton: nedefinováno;
}
}
Kodex implementuje a hlídat, jak je uvedeno v oficiální dokumentaci, chránit trasy a zajistit, aby k nim měli přístup pouze ověření uživatelé s platným tokenem JWT.
Extrahuje token JWT z hlavičky požadavku a ověří jeho pravost pomocí JwtService, a přiřadí dekódované užitečné zatížení k požadavek ['uživatel'] majetek k dalšímu zpracování. Pokud token chybí nebo je neplatný, hodí znak UnauthorizedException aby se zabránilo přístupu na chráněnou cestu.
Nyní vytvořte config.ts soubor ve stejném adresáři a přidejte níže uvedený kód.
vývozníkonst tajný klíč = {
tajný: 'TAJNÁ HODNOTA'.,
};
Tento tajný klíč se používá k podepisování a ověřování pravosti JWT. Je nezbytné bezpečně uložit hodnotu klíče, aby se zabránilo neoprávněnému přístupu a chránila integrita JWT.
Definujte API Controller
Vytvořte řadič, který zpracovává koncové body API pro ověřování uživatelů.
nest g controller user-auth
Dále zkopírujte kód uvedený v tomto Soubor úložiště GitHuba přidejte jej do user-auth.controller.ts soubor – definuje koncové body pro registraci uživatele, přihlášení a načítání uživatelských dat. The UseGuards (AuthGuard) dekorátor je zahrnut k vynucení autentizace pro getUsers koncový bod, což zajišťuje, že přístup mají pouze ověření uživatelé.
Aktualizujte soubor user-auth.module.ts
Chcete-li odrážet změny provedené v projektu, aktualizujte soubor user-auth.module.ts ke konfiguraci nezbytných modulů, služeb a řadičů pro ověřování uživatelů.
import { Modul, NestModule, MiddlewareConsumer } z'@nestjs/common';
import { JwtModule } z'@nestjs/jwt';
import { UserAuthController } z'./user-auth.controller';
import { UserAuthService } z'./user-auth.service';
import { MongooseModule } z'@nestjs/mongoose';
import { UserSchema } z'./schemas/user-auth.schema';
import { tajný klíč } z'./config';@Modul({
dovoz: [
MongooseModule.forFeature([{ name: 'Uživatel', schéma: UserSchema }]),
JwtModule.register({
tajemství: secretKey.secret,
signOptions: { expiresIn: '1h' },
}),
],
řadiče: [UserAuthController],
poskytovatelé: [UserAuthService],
})
vývoznítřída UserAuthModule nářadí NestModule {
configure (consumer: MiddlewareConsumer) {
}
}
Nakonec roztočte vývojový server a otestujte koncové body API pomocí Postman.
npm spuštění běhu
Vytváření bezpečných rozhraní REST API Nest.js
Vytváření bezpečných rozhraní Nest.js REST API vyžaduje komplexní přístup, který přesahuje pouhé spoléhání se na JWT při ověřování a autorizaci. I když jsou JWT důležité, je stejně důležité zavést další bezpečnostní opatření.
Navíc upřednostněním zabezpečení v každé fázi vývoje API můžete zajistit bezpečnost vašich backendových systémů.