Heim > Web-Frontend > js-Tutorial > Tag: Implementierung der JWT-Authentifizierung in NestJS mit Passport (Teil 1)

Tag: Implementierung der JWT-Authentifizierung in NestJS mit Passport (Teil 1)

Linda Hamilton
Freigeben: 2025-01-01 10:25:10
Original
193 Leute haben es durchsucht

Erste Schritte

Nest G-Ressourcenauthentifizierung

Dadurch werden Sie weiter nach einer Auswahl gefragt
❯ REST-API
GraphQL (Code zuerst)
GraphQL (Schema zuerst)
Microservice (nicht HTTP)
WebSockets

Wählen Sie REST API aus. Dadurch wird das gesamte Modul mit dem DTOS-Services-Controller und dem Modul für Sie generiert

Benutzer registrieren

Da wir als ersten Schritt die E-Mail-/Passwort-basierte Authentifizierung implementieren, werden wir den Benutzer registrieren.

  1. Validieren Sie zuerst, um sicherzustellen, dass die Daten legitim sind, und fügen Sie eine Validierung der Passwortstärke hinzu, um Brute-Force-Angriffe abzuwehren.
  2. Desinfizieren Sie anschließend, um sicherzustellen, dass die Daten sicher verwendet werden können.
  3. Überprüfen Sie, ob der Benutzerdatensatz bereits in der Datenbank vorhanden ist. Wenn er vorhanden ist, bedeutet dies, dass der Benutzer bereits ein Konto hat. Senden Sie daher eine Antwort, dass diese E-Mail bereits registriert ist.
  4. Wenn die oben genannten Prüfungen fehlschlagen, bedeutet das, dass wir einen Benutzer registrieren müssen Nehmen Sie das Benutzerpasswort und hashen Sie es mit einer guten Hashing-Bibliothek wie bcrypt oder argon2
  5. Fügen Sie nach dem Hashing den Benutzerdatensatz in die Datenbank ein.
  6. Senden Sie eine E-Mail an den Benutzer, um zu überprüfen, ob die E-Mail legitim ist.
  7. Fügen Sie der Route eine Ratenbegrenzung hinzu, um DDoS-Angriffe zu vermeiden

1 Eingehende Daten validieren

Da Nest Js eine starke Integration mit empfohlenen Validierungspaketen wie dem Klassenvalidator aufweist, verwende ich jedoch aufgrund meiner früheren Erfahrung häufig Zod für die Validierung in React-JS-Frontends und habe daher ein tolles
gefunden Eine Lösung für das Nest-JS-Ökosystem namens Nests Zod, daher werde ich mich vorerst lieber für diese entscheiden. Um zu beginnen, installieren Sie zunächst die Bibliothek
npm i nestjs-zod

import { createZodDto } from 'nestjs-zod';
import { z } from 'zod';
const passwordStrengthRegex =
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
const registerUserSchema = z
  .object({
    email: z.string().email(),
    password: z
      .string()
      .min(8)
      .regex(
        passwordStrengthRegex,
        'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
      ),
    confirmPassword: z.string().min(8),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: 'Passwords do not match',
  });

export class RegisterUserDto extends createZodDto(registerUserSchema) {}

Nach dem Login kopieren
Nach dem Login kopieren

und wenden Sie dann die Validierungspipe auf der Route an

import { Controller, Post, Body, Version, UsePipes } from '@nestjs/common';
import { AuthService } from './auth.service';
import { RegisterUserDto } from './dto/register.dto';
import { ZodValidationPipe } from 'nestjs-zod';

@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @Version('1')
  @Post()
  @UsePipes(ZodValidationPipe)
  async registerUser(@Body() registerUserDto: RegisterUserDto) {
    return await this.authService.registerUser(registerUserDto);
  }
}

Nach dem Login kopieren
Nach dem Login kopieren

wenn wir alle Eingaben korrekt bereitstellen

Day  Implementing JWT Authentication in NestJS with Passport (Part 1)

somit sind wir mit dem ersten Schritt fertig

Lassen Sie uns Daten bereinigen

wir haben drei Eingänge

  • Passwort: Normalerweise sollten Passwörter nicht bereinigt werden, da sie niemals an das Frontend gesendet und angezeigt werden, selbst wenn jemand ein bösartiges Skript an das Passwort sendet. Schließlich wird es gehasht, was nicht erforderlich ist
  • Passwort bestätigen: Gleiche Geschichte wie oben
  • E-Mail: Ja, E-Mails werden an Clients gesendet und gerendert, daher muss das E-Mail-Feld bereinigt sein, um Injektionen und Skriptangriffe abzuwehren

aber wir haben explizit E-Mail hinzugefügt: z.string().email(), was für diesen Anwendungsfall ausreicht
Day  Implementing JWT Authentication in NestJS with Passport (Part 1)

aber um noch mehr Sicherheit zu bieten, können wir eine Desinfektionsschicht hinzufügen

import { createZodDto } from 'nestjs-zod';
import { z } from 'zod';
import * as xss from 'xss'; 

const passwordStrengthRegex =
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;

const registerUserSchema = z
  .object({
    email: z.string().transform((input) => xss.filterXSS(input)), // Sanitizing input using xss
    password: z
      .string()
      .min(8)
      .regex(
        passwordStrengthRegex,
        'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
      ),
    confirmPassword: z.string().min(8),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: 'Passwords do not match',
  });

export class RegisterUserDto extends createZodDto(registerUserSchema) {}

Nach dem Login kopieren
Nach dem Login kopieren

Day  Implementing JWT Authentication in NestJS with Passport (Part 1)

Das war ein Test, den wir auch wieder hinzugefügt haben

E-Mail: z
.string()
.email()

Schritt 3,4,5

import { createZodDto } from 'nestjs-zod';
import { z } from 'zod';
const passwordStrengthRegex =
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
const registerUserSchema = z
  .object({
    email: z.string().email(),
    password: z
      .string()
      .min(8)
      .regex(
        passwordStrengthRegex,
        'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
      ),
    confirmPassword: z.string().min(8),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: 'Passwords do not match',
  });

export class RegisterUserDto extends createZodDto(registerUserSchema) {}

Nach dem Login kopieren
Nach dem Login kopieren

Der wichtigste Punkt, den ich beachten sollte: Ich habe gerade eine Erfolgsmeldung ohne Datenbezug zurückgegeben
B. ID oder E-Mail, da in diesem Schritt keine Daten an den Benutzer zurückgesendet werden müssen. Nach der Registrierung wird der Benutzer zur Anmeldeseite weitergeleitet, um seine Daten einzugeben. Daher ist es eine gute Sicherheitsmaßnahme, das Senden unnötiger Daten zu vermeiden

Day  Implementing JWT Authentication in NestJS with Passport (Part 1)

Ratenbegrenzung

Die Implementierung der Ratenbegrenzung in NestJS ist sehr einfach. Installieren Sie einfach NestJS/Throttler, konfigurieren Sie es global und fertig.
Um das Paket zu installieren, führen Sie npm i --save @nestjs/throttler
aus

import { Controller, Post, Body, Version, UsePipes } from '@nestjs/common';
import { AuthService } from './auth.service';
import { RegisterUserDto } from './dto/register.dto';
import { ZodValidationPipe } from 'nestjs-zod';

@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @Version('1')
  @Post()
  @UsePipes(ZodValidationPipe)
  async registerUser(@Body() registerUserDto: RegisterUserDto) {
    return await this.authService.registerUser(registerUserDto);
  }
}

Nach dem Login kopieren
Nach dem Login kopieren

Dann fügen Sie NestJS Throttle Guard als globalen Guard hinzu

import { createZodDto } from 'nestjs-zod';
import { z } from 'zod';
import * as xss from 'xss'; 

const passwordStrengthRegex =
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;

const registerUserSchema = z
  .object({
    email: z.string().transform((input) => xss.filterXSS(input)), // Sanitizing input using xss
    password: z
      .string()
      .min(8)
      .regex(
        passwordStrengthRegex,
        'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
      ),
    confirmPassword: z.string().min(8),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: 'Passwords do not match',
  });

export class RegisterUserDto extends createZodDto(registerUserSchema) {}

Nach dem Login kopieren
Nach dem Login kopieren

und hier ist es

import {
  BadRequestException,
  Injectable,
  InternalServerErrorException,
} from '@nestjs/common';
import { RegisterUserDto } from './dto/register.dto';
import { PrismaService } from 'src/prismaModule/prisma.service';
import * as argon2 from 'argon2';

@Injectable()
export class AuthService {
  constructor(private readonly prismaService: PrismaService) {}
  async registerUser(registerUserDto: RegisterUserDto) {
    // data is validate and sanitized by the registerUserDto
    const { email, password } = registerUserDto;

    try {
      // check if user already exists
      const user = await this.prismaService.user.findFirst({
        where: {
          email,
        },
      });

      if (user) {
        throw new BadRequestException('user already eists ');
      }
      //if use not exists lets hash user password
      const hashedPassword = await argon2.hash(registerUserDto.password);

      // time to create user
      const userData = await this.prismaService.user.create({
        data: {
          email,
          password: hashedPassword,
        },
      });

      if (!userData) {
        throw new InternalServerErrorException(
          'some thing went wrong while registring user',
        );
      }

      // if user is created successfully then  send email to user for email varification
      return {
        success: true,
        message: 'user created successfully',
      };
    } catch (error) {
      throw error;
    }
  }
}

Nach dem Login kopieren

da die Registrierung des Benutzerendpunkts ein sensibler Endpunkt-Brute-Force-Angriff ist
Andernfalls kann es zu einem Wörterbuchangriff kommen. Wir haben die Ratenbegrenzung streng gehalten

Verifizierungs-E-Mail senden

zum Senden einer Bestätigungs-E-Mail an einen Benutzer. Resend ist ein fantastischer, benutzerfreundlicher Dienst. Aber ich habe beschlossen, eine separate Episode für den gesamten Benachrichtigungsdienst zu erstellen, damit es für alle einfacher zu verstehen ist

Das obige ist der detaillierte Inhalt vonTag: Implementierung der JWT-Authentifizierung in NestJS mit Passport (Teil 1). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage