Gør brug af Nests strukturerede arkitektur til at bygge sikre og effektive REST API'er.

Express.js er en fantastisk teknologi til at bygge sikre og robuste REST API'er, men den giver ikke en foruddefineret struktur. Dens minimalistiske natur giver dig mulighed for at håndtere væsentlige aspekter som routing, kodeorganisering og sikkerhedsforanstaltninger enten manuelt eller ved at udnytte tilgængelig middleware og biblioteker.

I modsætning hertil introducerer Nest.js, bygget oven på Express.js og Node.js, en abstraktion på højere niveau der tilbyder en klar struktur, en robust kodeorganiseringstilgang og forenklet implementering detaljer. Grundlæggende giver Nest.js en mere struktureret arkitektur til at bygge effektive og sikre backend API'er og tjenester.

Opsætning af et Nest.js-projekt

For at komme i gang skal du først installere Nest.js' kommandolinje (CLI) globalt ved at køre kommandoen nedenfor:

npm i -g @nestjs/cli

Når installationen er færdig, skal du gå videre og oprette et nyt projekt ved at køre:

nest new nest-jwt-api

Dernæst vil Nest.js CLI bede dig om at vælge en pakkehåndtering til at installere afhængighederne. Til denne tutorial bruger vi npm, Node Package Manager. Vælg npm og vent, mens CLI'en opretter et grundlæggende Nest.js-projekt og installerer alle de nødvendige konfigurationsfiler og indledende afhængigheder, der kræves for at køre applikationen.

Når projektet er konfigureret, skal du navigere til projektbiblioteket og starte udviklingsserveren.

cd nest-jwt-api
npm løb start

Kør endelig kommandoen nedenfor for at installere de pakker, vi skal bruge til dette projekt.

npm installer mongodb mongoose @nestjs/mongoose @types/bcrypt bcrypt jsonwebtoken @nestjs/jwt

Du kan finde dette projekts kode i denne GitHub-depot.

Konfigurer MongoDB-databaseforbindelse

Opsæt en MongoDB-database lokalt eller konfigurere en MongoDB-klynge i skyen. Efter opsætning af databasen, kopier databaseforbindelsens URI-streng, opret en .env fil i rodmappen i vores projektmappe, og indsæt forbindelsesstrengen:

MONGO_URI="forbindelsesstreng"

Opdater derefter app.modul.ts i src mappefil for at konfigurere Mongoose som følger:

importere { Modul } fra'@nestjs/common';
importere { ConfigModule } fra'@nestjs/config';
importere { MongooseModule } fra'@nestjs/mongoose';
importere { AppController } fra'./app.controller';
importere { AppService } fra'./app.service';
importere { UserAuthModule } fra'./user-auth/user-auth.module';

@Modul({
import: [
ConfigModule.forRoot({
envFilePath: '.env',
isGlobal: rigtigt,
}),
MongooseModule.forRoot (process.env. MONGO_URI),
UserAuthModule,
],
controllere: [AppController],
udbydere: [AppService],
})

eksportklasse AppModule {}

Den medfølgende kode konfigurerer tre væsentlige moduler til Nest.js-applikationen: ConfigModule til miljøkonfiguration, MongooseModul til etablering af MongoDB-forbindelsen, og UserAuthModule til brugergodkendelse. Bemærk venligst, at der på dette stadium kan opstå en fejl siden UserAuthModule er endnu ikke defineret, men vi opretter det i næste afsnit.

Oprettelse af brugergodkendelsesmodulet

For at opretholde ren og velorganiseret kode skal du oprette et brugergodkendelsesmodul ved at køre følgende kommando.

nest g modul brugergodkendelse

Nest.js CLI-værktøjet genererer automatisk de nødvendige modulfiler. Derudover vil den opdatere app.modul.ts fil, der inkorporerer de nødvendige ændringer relateret til brugergodkendelsesmodulet.

Du kan vælge at oprette hovedprojektets konfigurationsfiler manuelt, ikke desto mindre forenkler CLI-værktøjet denne proces ved automatisk at oprette de nødvendige elementer, ud over at opdatere ændringerne i overensstemmelse hermed i det app.modul.ts fil.

Opret et brugerskema

Inde i det nyoprettede brugergodkendelse mappe i src mappe, skal du oprette en ny schemas/user-auth.schema.ts fil, og tilføj følgende kode for at oprette et Mongoose-skema for Bruger model

importere { Prop, Schema, SchemaFactory } fra'@nestjs/mongoose';
importere { Dokument } fra'mangust';

@Skema({ tidsstempler: rigtigt })
eksportklasse Bruger {
@Rekvisit()
brugernavn: snor;
@Rekvisit()
adgangskode: snor;
}

eksporttype UserDocument = Bruger & Dokument;
eksportkonst UserSchema = SchemaFactory.createForClass (Bruger);

Oprettelse af brugergodkendelsestjenesten

Lad os nu oprette brugergodkendelsestjenesten, der administrerer godkendelseslogikken for REST API ved at køre kommandoen nedenfor:

nest g service brugergodkendelse

Denne kommando vil oprette en user-auth.service.ts fil inde i brugergodkendelsesmappen. Åbn denne fil og opdater den med følgende kode.

  1. Foretag først følgende importer.
    importere { Injectable, NotFoundException, Logger, UnauthorizedException } fra'@nestjs/common';
    importere { InjectModel } fra'@nestjs/mongoose';
    importere { Model } fra'mangust';
    importere { Bruger } fra'./schemas/user-auth.schema';
    importere * som bcrypt fra'bcrypt';
    importere { JwtService } fra'@nestjs/jwt';
  2. Opret derefter en UserAuthService klasse, der indkapsler funktionaliteten til brugerregistrering, login og hentning af alle brugerdataruter.
@Injicerbar()
eksportklasse UserAuthService {
privat skrivebeskyttet logger = ny Logger (UserAuthService.name);
konstruktør(@InjectModel(Bruger.navn) privat brugerModel: Model, privat jwtService: JwtService) {}

asynkron registerBruger (brugernavn: snor, adgangskode: snor): Løftesnor }> {
prøve {
konst hash = vente bcrypt.hash (adgangskode, 10);
ventedet her.userModel.create({ brugernavn, adgangskode: hash });
Vend tilbage { besked: 'Bruger registreret med succes' };
} fangst (fejl) {
kastenyFejl('Der opstod en fejl under registrering af brugeren');
}
 }

asynkron loginBruger (brugernavn: snor, adgangskode: snor): Løfte<snor> {
prøve {
konst bruger = ventedet her.userModel.findOne({ brugernavn });
hvis (!bruger) {
kasteny NotFoundException('Bruger ikke fundet');
}
konst passwordMatch = vente bcrypt.compare (adgangskode, bruger.password);
hvis (!passwordMatch) {
kasteny Uautoriseret Undtagelse('Ugyldige loginoplysninger');
}
konst nyttelast = { userId: user._id };
konst token = det her.jwtService.sign (nyttelast);
Vend tilbage polet;
} fangst (fejl) {
konsol.log (fejl);
kasteny Uautoriseret Undtagelse('Der opstod en fejl under login');
}
}

asynkron getUsers(): Løfte {
prøve {
konst brugere = ventedet her.userModel.find({});
Vend tilbage brugere;
} fangst (fejl) {
det her.logger.error(`Der opstod en fejl under hentning af brugere: ${error.message}`);
kastenyFejl('Der opstod en fejl under hentning af brugere');
}
}
}

Det UserAuthService klasse implementerer logikken for brugerregistrering, login og hentning af brugerdata. Den bruger brugermodel at interagere med databasen og udføre de nødvendige handlinger, herunder hashing af adgangskoden under registrering, validering af login-legitimationsoplysninger og til sidst generering af JWT-tokens efter succes Godkendelse.

Implementering af Authentication Guard

For at sikre sikkerheden af ​​følsomme ressourcer er det afgørende at begrænse adgangen udelukkende til autoriserede brugere. Dette opnås ved at håndhæve en sikkerhedsforanstaltning, der påbyder tilstedeværelsen af ​​en gyldig JWT i efterfølgende API-anmodninger til beskyttede slutpunkter, i dette tilfælde brugere rute. I brugergodkendelse mappe, skal du oprette en ny auth.guard.ts fil og tilføj koden nedenfor.

importere { CanActivate, ExecutionContext, Injectable, UnauthorizedException } fra'@nestjs/common';
importere { JwtService } fra'@nestjs/jwt';
importere { Anmodning } fra'udtrykke';
importere { secretKey } fra'./config';

@Injicerbar()
eksportklasse AuthGuard redskaber CanActivate {
konstruktør(privat jwtService: JwtService) {}

asynkron canActivate (kontekst: ExecutionContext): Løfte<boolesk> {
konst request = context.switchToHttp().getRequest();
konst token = det her.extractTokenFromHeader (anmodning);
hvis (!polet) {
kasteny Uautoriseret Undtagelse();
}
prøve {
konst nyttelast = ventedet her.jwtService.verifyAsync (token, {
hemmelighed: secretKey.secret,
});
anmodning['bruger'] = nyttelast;
} fangst {
kasteny Uautoriseret Undtagelse();
}
Vend tilbagerigtigt;
}
privat extractTokenFromHeader (anmodning: Anmodning): snor | udefineret {
konst [type, token] = request.headers.authorization?.split(' ')?? [];
Vend tilbagetype'Bærer'? polet: udefineret;
}
}

Koden implementerer en vagt, som specificeret i den officielle dokumentation, for at beskytte ruter og sikre, at kun godkendte brugere med et gyldigt JWT-token kan få adgang til dem.

Den udtrækker JWT-tokenet fra anmodningshovedet, verificerer dets ægthed ved hjælp af JwtService, og tildeler den afkodede nyttelast til anmodning['bruger'] ejendom til videre behandling. Hvis tokenet mangler eller er ugyldigt, kaster det en Uautoriseret Undtagelse for at forhindre adgang til den beskyttede rute.

Nu, opret config.ts fil i samme mappe, og tilføj koden nedenfor.

eksportkonst hemmelig nøgle = {
hemmelighed: 'SEKTRETVÆRDI.',
};

Denne hemmelige nøgle bruges til at signere og verificere ægtheden af ​​JWT'er. Det er vigtigt at opbevare nøgleværdien sikkert for at forhindre uautoriseret adgang og beskytte JWT'ernes integritet.

Definer API-controlleren

Opret en controller, der håndterer API-endepunkterne til brugergodkendelse.

nest g controller brugergodkendelse

Kopier derefter koden, der er angivet i denne GitHub repository fil, og føj det til user-auth.controller.ts fil – den definerer slutpunkterne for brugerregistrering, login og hentning af brugerdata. Det UseGuards (AuthGuard) dekorator er inkluderet for at håndhæve autentificering for getUsers slutpunkt, hvilket sikrer, at kun godkendte brugere får adgang.

Opdater user-auth.module.ts-filen

For at afspejle de ændringer, der er foretaget i projektet, skal du opdatere user-auth.module.ts fil for at konfigurere de nødvendige moduler, tjenester og controllere til brugergodkendelse.

importere { Module, NestModule, MiddlewareConsumer } fra'@nestjs/common';
importere { JwtModule } fra'@nestjs/jwt';
importere { UserAuthController } fra'./user-auth.controller';
importere { UserAuthService } fra'./user-auth.service';
importere { MongooseModule } fra'@nestjs/mongoose';
importere { Brugerskema } fra'./schemas/user-auth.schema';
importere { secretKey } fra'./config';

@Modul({
import: [
MongooseModule.forFeature([{ navn: 'Bruger', skema: UserSchema }]),
JwtModule.register({
hemmelighed: secretKey.secret,
signOptions: { expiresIn: '1h' },
}),
],
controllere: [UserAuthController],
udbydere: [UserAuthService],
})

eksportklasse UserAuthModule redskaber NestModule {
configure (forbruger: MiddlewareConsumer) {
}
}

Drej til sidst udviklingsserveren op og test API-endepunkterne ved hjælp af Postman.

npm løb start

Opbygning af sikre Nest.js REST API'er

Opbygning af sikre Nest.js REST API'er kræver en omfattende tilgang, der rækker ud over blot at stole på JWT'er til godkendelse og autorisation. Selvom JWT'er er vigtige, er det lige så vigtigt at implementere yderligere sikkerhedsforanstaltninger.

Derudover kan du ved at prioritere sikkerheden på alle stadier af API-udvikling sikre sikkerheden af ​​dine backend-systemer.