Folosiți arhitectura structurată a Nest pentru a crea API-uri REST sigure și eficiente.

Express.js este o tehnologie excelentă pentru construirea de API-uri REST sigure și robuste, cu toate acestea, nu oferă o structură predefinită. Natura sa minimalistă vă permite să gestionați aspecte esențiale precum rutarea, organizarea codului și măsurile de securitate, fie manual, fie utilizând middleware și biblioteci disponibile.

În schimb, Nest.js, construit pe deasupra Express.js și Node.js, introduce o abstractizare de nivel superior care oferă o structură clară, o abordare robustă de organizare a codului și implementare simplificată Detalii. În esență, Nest.js oferă o arhitectură mai structurată pentru construirea de API și servicii de backend eficiente și sigure.

Configurarea unui proiect Nest.js

Pentru a începe, mai întâi trebuie să instalați linia de comandă (CLI) a Nest.js la nivel global, rulând comanda de mai jos:

npm i -g @nestjs/cli

Odată ce instalarea este finalizată, continuați și creați un nou proiect, rulând:

instagram viewer
cuib nou cuib-jwt-api

Apoi, Nest.js CLI vă va solicita să alegeți un manager de pachete pentru a instala dependențele. Pentru acest tutorial, vom folosi npm, Managerul de pachete Node. Selectați npm și așteptați până când CLI creează un proiect Nest.js de bază și instalează toate fișierele de configurare necesare și dependențele inițiale necesare pentru a rula aplicația.

După ce proiectul este configurat, navigați la directorul proiectului și porniți serverul de dezvoltare.

cd cuib-jwt-api
npm run start

În cele din urmă, rulați comanda de mai jos pentru a instala pachetele pe care le vom folosi pentru acest proiect.

npm instalează mongodb mongoose @nestjs/mongoose @types/bcrypt bcrypt jsonwebtoken @nestjs/jwt

Puteți găsi codul acestui proiect în aceasta Depozitul GitHub.

Configurați conexiunea la baza de date MongoDB

Configurați o bază de date MongoDB local sau configurați un cluster MongoDB pe cloud. După configurarea bazei de date, copiați șirul URI de conexiune la baza de date, creați un .env fișier în directorul rădăcină al folderului nostru de proiect și lipiți în șirul de conexiune:

MONGO_URI="șir de conexiune"

Apoi, actualizați aplicație.modul.ts în src fișier director pentru a configura Mongoose după cum urmează:

import { Modulul } din„@nestjs/common”;
import { ConfigModule } din„@nestjs/config”;
import { MongooseModule } din„@nestjs/mongoose”;
import { AppController } din„./app.controller”;
import { AppService } din„./app.service”;
import { UserAuthModule } din„./user-auth/user-auth.module”;

@Modul({
importuri: [
ConfigModule.forRoot({
envFilePath: „.env”,
isGlobal: Adevărat,
}),
MongooseModule.forRoot (process.env. MONGO_URI),
UserAuthModule,
],
controlere: [AppController],
furnizori: [AppService],
})

exportclasă AppModule {}

Codul furnizat configurează trei module esențiale pentru aplicația Nest.js: ConfigModule pentru configurarea mediului, MangooseModule pentru stabilirea conexiunii MongoDB și UserAuthModule pentru autentificarea utilizatorului. Vă rugăm să rețineți că, în această etapă, poate apărea o eroare, deoarece UserAuthModule nu este încă definit, dar îl vom crea în secțiunea următoare.

Crearea modulului de autentificare a utilizatorului

Pentru a menține codul curat și bine organizat, creați un modul de autentificare a utilizatorului rulând următoarea comandă.

Nest g module user-auth

Instrumentul CLI Nest.js generează automat fișierele de modul necesare. În plus, va actualiza aplicație.modul.ts fișier, încorporând modificările necesare legate de modulul de autentificare a utilizatorului.

Puteți opta pentru crearea manuală a fișierelor principale de configurare a proiectului, cu toate acestea, instrumentul CLI simplifică acest proces prin crearea automată a elementelor necesare, în plus față de actualizarea modificărilor în consecință în cel aplicație.modul.ts fişier.

Creați o schemă de utilizator

În interiorul nou creat utilizator-auth folderul în src director, creați un nou schemes/user-auth.schema.ts fișier și adăugați următorul cod pentru a crea o schemă Mongoose pentru Utilizator model

import { Prop, Schema, SchemaFactory } din„@nestjs/mongoose”;
import { Document } din'mangustă';

@Schemă({ marcaje temporale: Adevărat })
exportclasă Utilizator {
@Recuzită()
nume de utilizator: şir;
@Recuzită()
parola: şir;
}

exporttip UserDocument = Utilizator & Document;
exportconst UserSchema = SchemaFactory.createForClass (Utilizator);

Crearea serviciului de autentificare a utilizatorilor

Acum, să creăm serviciul de autentificare a utilizatorilor care va gestiona logica de autentificare pentru API-ul REST, rulând comanda de mai jos:

nest g service user-auth

Această comandă va crea un user-auth.service.ts fișier din directorul user-auth. Deschideți acest fișier și actualizați-l cu următorul cod.

  1. Mai întâi, faceți următoarele importuri.
    import { Injectabil, NotFoundException, Logger, UnauthorizedException } din„@nestjs/common”;
    import { InjectModel } din„@nestjs/mongoose”;
    import { Model } din'mangustă';
    import { Utilizator } din„./schemas/user-auth.schema”;
    import * la fel de bcrypt din'bcrypt';
    import { JwtService } din„@nestjs/jwt”;
  2. Apoi, creați un UserAuthService clasă care încapsulează funcționalitatea pentru înregistrarea utilizatorului, autentificare și preluarea tuturor rutelor de date ale utilizatorului.
@Injectabil()
exportclasă UserAuthService {
privat readonly logger = nou Logger (UserAuthService.name);
constructor(@InjectModel(Nume de utilizator) privat userModel: Model, privat jwtService: JwtService) {}

asincron registerUser (nume utilizator: şir, parola: şir): Promisiuneşir }> {
încerca {
const hash = așteaptă bcrypt.hash (parolă, 10);
așteaptăacest.userModel.create({ nume de utilizator, parola: hash });
întoarcere { mesaj: „Utilizatorul s-a înregistrat cu succes” };
} captură (eroare) {
aruncanouEroare(„A apărut o eroare la înregistrarea utilizatorului”);
}
 }

asincron loginUser (nume utilizator: şir, parola: şir): Promisiune<şir> {
încerca {
const utilizator = așteaptăacest.userModel.findOne({ nume de utilizator });
dacă (!utilizator) {
aruncanou NotFoundException('Utilizator nu a fost găsit');
}
const passwordMatch = așteaptă bcrypt.compare (parolă, utilizator.parolă);
dacă (!passwordMatch) {
aruncanou UnauthorizedException(„Acreditări de conectare nevalide”);
}
const sarcină utilă = { userId: user._id };
const token = acest.jwtService.sign (sarcină utilă);
întoarcere jeton;
} captură (eroare) {
consolă.log (eroare);
aruncanou UnauthorizedException(„A apărut o eroare la conectare”);
}
}

asincron getUsers(): Promisiune {
încerca {
const utilizatori = așteaptăacest.userModel.find({});
întoarcere utilizatorii;
} captură (eroare) {
acest.logger.error(„A apărut o eroare la preluarea utilizatorilor: ${error.message}`);
aruncanouEroare(„A apărut o eroare la preluarea utilizatorilor”);
}
}
}

The UserAuthService clasa implementează logica de înregistrare a utilizatorului, autentificare și preluare a datelor utilizatorului. Acesta folosește userModel pentru a interacționa cu baza de date și a efectua acțiunile necesare, inclusiv hashingul parolei în timpul înregistrare, validarea acreditărilor de conectare și, în sfârșit, generarea de jetoane JWT după succes autentificare.

Implementarea Gărzii de autentificare

Pentru a asigura securitatea resurselor sensibile, este crucial să se limiteze accesul exclusiv la utilizatorii autorizați. Acest lucru se realizează prin aplicarea unei măsuri de securitate care impune prezența unui JWT valid în solicitările API ulterioare efectuate către punctele finale protejate, în acest caz, utilizatorii traseu. În utilizator-auth director, creați un nou auth.guard.ts fișier și adăugați codul de mai jos.

import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } din„@nestjs/common”;
import { JwtService } din„@nestjs/jwt”;
import { Cerere } din'expres';
import { cheie secreta } din'./config';

@Injectabil()
exportclasă AuthGuard unelte CanActivate {
constructor(privat jwtService: JwtService) {}

asincron canActivate (context: ExecutionContext): Promisiune<boolean> {
const cerere = context.switchToHttp().getRequest();
const token = acest.extractTokenFromHeader (cerere);
dacă (!token) {
aruncanou UnauthorizedException();
}
încerca {
const sarcina utila = așteaptăacest.jwtService.verifyAsync (indicativ, {
secret: secretKey.secret,
});
cerere['utilizator'] = sarcină utilă;
} captură {
aruncanou UnauthorizedException();
}
întoarcereAdevărat;
}
privat extractTokenFromHeader (cerere: Solicitare): şir | nedefinit {
const [tip, token] = request.headers.authorization?.split(' ')?? [];
întoarceretip'Purtător'? jeton: nedefinit;
}
}

Codul implementează a paza, așa cum este specificat în documentația oficială, pentru a proteja rutele și a se asigura că doar utilizatorii autentificați cu un token JWT valid le pot accesa.

Acesta extrage jetonul JWT din antetul cererii, își verifică autenticitatea folosind JwtService, și atribuie sarcina utilă decodificată cerere['utilizator'] proprietate pentru prelucrare ulterioară. Dacă jetonul lipsește sau este invalid, acesta aruncă un UnauthorizedException pentru a împiedica accesul la traseul protejat.

Acum, creează config.ts fișier în același director și adăugați codul de mai jos.

exportconst secretKey = {
secret: „VALOARE SECRETĂ”.,
};

Această cheie secretă este utilizată pentru a semna și a verifica autenticitatea JWT-urilor. Este esențial să stocați valoarea cheii în siguranță pentru a preveni accesul neautorizat și pentru a proteja integritatea JWT-urilor.

Definiți controlerul API

Creați un controler care se ocupă de punctele finale API pentru autentificarea utilizatorului.

controler nest g user-auth

Apoi, copiați codul furnizat în aceasta Fișierul depozitului GitHub, și adăugați-l la user-auth.controller.ts fișier — definește punctele finale pentru înregistrarea utilizatorului, autentificare și preluarea datelor utilizatorului. The UseGuards (AuthGuard) Decorator este inclus pentru a impune autentificarea pentru getUsers punct final, asigurându-se că numai utilizatorilor autentificați li se acordă acces.

Actualizați fișierul user-auth.module.ts

Pentru a reflecta modificările aduse proiectului, actualizați user-auth.module.ts fișier pentru a configura modulele, serviciile și controlerele necesare pentru autentificarea utilizatorului.

import { Module, NestModule, MiddlewareConsumer } din„@nestjs/common”;
import { JwtModule } din„@nestjs/jwt”;
import { UserAuthController } din„./user-auth.controller”;
import { UserAuthService } din„./user-auth.service”;
import { MongooseModule } din„@nestjs/mongoose”;
import { UserSchema } din„./schemas/user-auth.schema”;
import { cheie secreta } din'./config';

@Modul({
importuri: [
MongooseModule.forFeature([{ nume: 'Utilizator', schema: UserSchema }]),
JwtModule.register({
secret: secretKey.secret,
signOptions: { expiresIn: '1h' },
}),
],
controlere: [UserAuthController],
furnizori: [UserAuthService],
})

exportclasă UserAuthModule unelte NestModule {
configura (consumator: MiddlewareConsumer) {
}
}

În cele din urmă, porniți serverul de dezvoltare și testați punctele finale API folosind Postman.

npm run start

Crearea de API-uri REST Nest.js securizate

Crearea de API-uri REST Nest.js sigure necesită o abordare cuprinzătoare care depășește doar bazarea pe JWT pentru autentificare și autorizare. Deși JWT-urile sunt importante, este la fel de important să se implementeze măsuri de securitate suplimentare.

În plus, acordând prioritate securității în fiecare etapă a dezvoltării API-ului, puteți asigura securitatea sistemelor dvs. de backend.