nest g 리소스 인증
추가로 선택을 요청합니다
❯ REST API
GraphQL(코드 우선)
GraphQL(스키마 우선)
마이크로서비스(비HTTP)
웹소켓
REST API를 선택하면 dtos 서비스 컨트롤러 및 모듈을 사용하여 전체 모듈이 생성됩니다
이메일/비밀번호 기반 인증을 첫 번째 단계로 구현하고 있으므로 사용자를 등록하겠습니다.
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); } }
모든 입력이 올바른 경우
이제 첫 번째 단계가 끝났습니다
3개의 입력이 있습니다
하지만 명시적으로 이메일을 추가했습니다: z.string().email() 이 사용 사례에 충분합니다
하지만 보안을 강화하기 위해 위생 처리 레이어를 추가할 수 있습니다
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) {}
이것은 우리가 다시 추가한 테스트였습니다
이메일: z
.string()
.이메일()
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나 이메일과 같이 사용자에게 전달됩니다. 등록 후 사용자는 세부 정보를 입력하기 위해 로그인 페이지로 리디렉션되므로 불필요한 데이터 전송을 피하는 것이 보안상 좋은 습관입니다.
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!