> 웹 프론트엔드 > JS 튜토리얼 > Passport를 사용하여 NestJS에서 JWT 인증을 구현하는 날(1부)

Passport를 사용하여 NestJS에서 JWT 인증을 구현하는 날(1부)

Linda Hamilton
풀어 주다: 2025-01-01 10:25:10
원래의
194명이 탐색했습니다.

첫 번째 단계

nest g 리소스 인증

추가로 선택을 요청합니다
❯ REST API
GraphQL(코드 우선)
GraphQL(스키마 우선)
마이크로서비스(비HTTP)
웹소켓

REST API를 선택하면 dtos 서비스 컨트롤러 및 모듈을 사용하여 전체 모듈이 생성됩니다

사용자 등록

이메일/비밀번호 기반 인증을 첫 번째 단계로 구현하고 있으므로 사용자를 등록하겠습니다.

  1. 먼저 검증하여 데이터가 합법적인지 확인하고 비밀번호 강도 검증을 추가하여 무차별 대입 공격을 완화하세요.
  2. 데이터를 안전하게 사용할 수 있도록 나중에 정리하세요.
  3. 사용자 기록이 이미 데이터베이스에 있는지 확인하세요. 존재하는 경우 이는 사용자가 이미 계정을 가지고 있다는 의미이므로 이미 등록된 이메일이라는 응답을 보내세요.
  4. 위 확인이 실패하면 사용자를 등록해야 함을 의미합니다. 사용자 비밀번호를 가져와 bcrypt 또는 argon2와 같은 좋은 해싱 라이브러리로 해시합니다
  5. 해싱 후 사용자 레코드를 DB에 삽입합니다.
  6. 사용자에게 이메일을 보내 이메일이 합법적인지 확인하세요.
  7. DDoS 공격을 피하기 위해 경로에 속도 제한 추가

1 수신 데이터의 유효성을 검사합니다.

nest js는 클래스 유효성 검사기와 같은 권장 유효성 검사 패키지와 강력하게 통합되어 있기 때문에 이전 경험에 따르면 반응 js 프런트 엔드의 유효성 검사 로트에 zod를 사용하여 멋진 것을 발견했습니다.
Nests zod라는 Nest js 생태계용 솔루션이므로 지금은 이 솔루션을 선호하겠습니다. 시작하려면 먼저 라이브러리를 설치하세요
npm과 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) {}

로그인 후 복사
로그인 후 복사

그런 다음 경로에 유효성 검사 파이프를 적용합니다

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);
  }
}

로그인 후 복사
로그인 후 복사

모든 입력이 올바른 경우

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

이제 첫 번째 단계가 끝났습니다

데이터를 삭제하자

3개의 입력이 있습니다

  • 비밀번호: 일반적으로 비밀번호는 누군가가 악성 스크립트를 보내더라도 프런트엔드에 전송 및 표시되지 않으므로 결국 비밀번호는 해시화되므로 삭제하면 안 됩니다.
  • confirmPassword: 위와 같은 내용
  • 이메일: 예, 이메일은 클라이언트에게 전송되고 렌더링되므로 주입 및 스크립팅 공격을 완화하려면 이메일 필드를 삭제해야 합니다.

하지만 명시적으로 이메일을 추가했습니다: z.string().email() 이 사용 사례에 충분합니다
Day  Implementing JWT Authentication in NestJS with Passport (Part 1)

하지만 보안을 강화하기 위해 위생 처리 레이어를 추가할 수 있습니다

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) {}

로그인 후 복사
로그인 후 복사

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

이것은 우리가 다시 추가한 테스트였습니다

이메일: z
.string()
.이메일()

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) {}

로그인 후 복사
로그인 후 복사

주의할점 관련 데이터 없이 방금 성공 메시지만 보냈네요
이 단계에서는 사용자에게 데이터를 다시 보낼 필요가 없기 때문에 ID나 이메일과 같이 사용자에게 전달됩니다. 등록 후 사용자는 세부 정보를 입력하기 위해 로그인 페이지로 리디렉션되므로 불필요한 데이터 전송을 피하는 것이 보안상 좋은 습관입니다.

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

비율 제한

nestjs에서 속도 제한을 구현하는 것은 매우 쉽습니다. 단지 Nestjs/throttler를 설치하고 전역적으로 구성하면 완료됩니다.
패키지를 설치하려면 npm i --save @nestjs/throttler
를 실행하세요.

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);
  }
}

로그인 후 복사
로그인 후 복사

그런 다음 Nestjs 스로틀 가드를 전역 가드로 추가하세요

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) {}

로그인 후 복사
로그인 후 복사

여기 있습니다

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;
    }
  }
}

로그인 후 복사

사용자 엔드포인트 등록은 민감한 엔드포인트 무차별 공격이므로
또는 사전 공격이 발생할 수 있으므로 비율 제한을 엄격하게 유지했습니다

확인 이메일 보내기

사용자에게 확인 이메일을 보내기 위한 재전송은 사용하기 매우 쉬운 서비스입니다. 하지만 모두가 쉽게 이해할 수 있도록 전체 알림 서비스에 대해 별도의 에피소드를 만들기로 결정했습니다

위 내용은 Passport를 사용하여 NestJS에서 JWT 인증을 구현하는 날(1부)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿