nest g 資源授權
這將進一步要求您進行選擇
❯ REST API
GraphQL(代碼優先)
GraphQL(模式優先)
微服務(非 HTTP)
WebSocket
選擇 REST API,這將為您產生具有 dtos 服務控制器和模組的整個模組
由於我們實施基於電子郵件/密碼的身份驗證作為第一步,我們將註冊使用者。
由於 Nest js 與類驗證器等推薦的驗證包有很強的集成,但根據我之前的經驗,我在 React JS 前端使用 zod 進行驗證,所以我發現了一個很棒的
Nest js 生態系統的解決方案稱為 Nests Zod,所以我現在更喜歡使用這個。首先安裝庫
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); } }
如果我們提供的所有輸入都正確
這樣我們就完成了第一步
我們有三個輸入
但是我們明確地添加了電子郵件: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()
.email()
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); } }
然後加入nestjsthrottleguard作為全域守衛
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; } } }
因為註冊用戶端點是一個敏感端點暴力破解
否則可能會發生字典攻擊,我們嚴格限制速率
用於向使用者發送驗證電子郵件的使用 Resend 是一項非常棒的易於使用的服務。但我決定為整個通知服務創建一個單獨的劇集,以便每個人都更容易理解它
以上是在 NestJS 中使用 Passport 實作 JWT 驗證日(第 1 部分)的詳細內容。更多資訊請關注PHP中文網其他相關文章!