验证邮箱验证码

This commit is contained in:
秦秋旭 2023-02-24 11:21:36 +08:00
parent 56ae208717
commit abf41f3c95
4 changed files with 31 additions and 19 deletions

View File

@ -31,3 +31,8 @@ export class EmailVerifyDto {
@IsNotEmpty() @IsNotEmpty()
verifyCode: string verifyCode: string
} }
export class EmailVerifycationDto extends EmailVerifyDto {
@IsNotEmpty()
scene: EmailScene
}

View File

@ -6,11 +6,9 @@ import {
applyDecorators, applyDecorators,
UseGuards, UseGuards,
SetMetadata, SetMetadata,
ForbiddenException,
} from '@nestjs/common' } from '@nestjs/common'
import { EmailScene, EmailSendDto } from './dto/email.dto' import { EmailScene, EmailVerifyDto } from './dto/email.dto'
import { EmailService } from './email.service' import { EmailService } from './email.service'
import { JwtService } from '@nestjs/jwt'
import { type Request } from 'express' import { type Request } from 'express'
const EMAIL_SCENE_KEY = 'EMAIL_SCENE' const EMAIL_SCENE_KEY = 'EMAIL_SCENE'
@ -20,24 +18,16 @@ class EmailVeriyGuard implements CanActivate {
constructor( constructor(
private emailService: EmailService, private emailService: EmailService,
private reflector: Reflector, private reflector: Reflector,
private jwtService: JwtService,
) {} ) {}
canActivate(ctx: ExecutionContext) { async canActivate(ctx: ExecutionContext) {
const scene = this.reflector.get<EmailScene>( const scene = this.reflector.get<EmailScene>(
EMAIL_SCENE_KEY, EMAIL_SCENE_KEY,
ctx.getHandler(), ctx.getHandler(),
) )
const request = ctx.switchToHttp().getRequest<Request>() const body: EmailVerifyDto = ctx.switchToHttp().getRequest<Request>().body
const { token, email, verifyCode } = request.body await this.emailService.verifyEmailCode({ scene, ...body })
const payload = this.jwtService.verify<EmailSendDto>(token, {
secret: this.emailService.getEmailJwtSecret(verifyCode, scene),
})
if (payload.email !== email || payload.scene !== scene) {
throw new ForbiddenException('请输入正确的邮箱验证码')
}
return true return true
} }
} }

View File

@ -1,7 +1,7 @@
import { Body, Controller, Post } from '@nestjs/common' import { Body, Controller, Post, Get, Query } from '@nestjs/common'
import { EmailService } from './email.service' import { EmailService } from './email.service'
import { ApiTags, ApiOperation } from '@nestjs/swagger' import { ApiTags, ApiOperation } from '@nestjs/swagger'
import { EmailSendDto } from './dto/email.dto' import { EmailSendDto, EmailVerifycationDto } from './dto/email.dto'
@ApiTags('Email') @ApiTags('Email')
@Controller('api/email') @Controller('api/email')
@ -9,8 +9,14 @@ export class EmailController {
constructor(private readonly emailService: EmailService) {} constructor(private readonly emailService: EmailService) {}
@ApiOperation({ summary: '发送邮箱验证码' }) @ApiOperation({ summary: '发送邮箱验证码' })
@Post('verifyCode') @Get('verifyCode')
async sendEmailCode(@Body() payload: EmailSendDto) { async sendEmailCode(@Query() payload: EmailSendDto) {
return this.emailService.sendEmailToken(payload.email, payload.scene) return this.emailService.sendEmailToken(payload.email, payload.scene)
} }
@ApiOperation({ summary: '验证邮箱验证码' })
@Post('verifyCode')
async verifyEmailCode(@Body() payload: EmailVerifycationDto) {
return this.emailService.verifyEmailCode(payload)
}
} }

View File

@ -3,12 +3,13 @@ import {
Injectable, Injectable,
ConflictException, ConflictException,
NotFoundException, NotFoundException,
ForbiddenException,
} from '@nestjs/common' } from '@nestjs/common'
import { securityConfig, SecurityConfig } from 'src/common/configs' import { securityConfig, SecurityConfig } from 'src/common/configs'
import { MailerService } from '@nestjs-modules/mailer' import { MailerService } from '@nestjs-modules/mailer'
import { JwtService } from '@nestjs/jwt' import { JwtService } from '@nestjs/jwt'
import { PrismaService } from 'nestjs-prisma' import { PrismaService } from 'nestjs-prisma'
import { EmailScene } from './dto/email.dto' import { EmailScene, EmailVerifycationDto, EmailSendDto } from './dto/email.dto'
import { UserEntity } from 'src/users/entities/user.entity' import { UserEntity } from 'src/users/entities/user.entity'
@Injectable() @Injectable()
@ -59,6 +60,16 @@ export class EmailService {
return { token, userId: user?.id } return { token, userId: user?.id }
} }
async verifyEmailCode(data: EmailVerifycationDto) {
const { token, verifyCode, email, scene } = data
const payload = this.jwtService.verify<EmailSendDto>(token, {
secret: this.getEmailJwtSecret(verifyCode, scene),
})
if (payload.email !== email || payload.scene !== scene) {
throw new ForbiddenException('邮箱验证码验证失败')
}
}
getEmailJwtSecret(verifyCode: string, scene: EmailScene) { getEmailJwtSecret(verifyCode: string, scene: EmailScene) {
return this.secureConfig.jwt_access_secret + verifyCode + scene return this.secureConfig.jwt_access_secret + verifyCode + scene
} }