add JwtExceptionsFilter
This commit is contained in:
		
							parent
							
								
									2db40172b2
								
							
						
					
					
						commit
						085deabc7f
					
				| @ -35,6 +35,7 @@ | |||||||
|     "@nestjs/platform-express": "^9.0.0", |     "@nestjs/platform-express": "^9.0.0", | ||||||
|     "@nestjs/swagger": "^6.2.1", |     "@nestjs/swagger": "^6.2.1", | ||||||
|     "@prisma/client": "^4.10.1", |     "@prisma/client": "^4.10.1", | ||||||
|  |     "@types/jsonwebtoken": "^9.0.1", | ||||||
|     "bcrypt": "^5.1.0", |     "bcrypt": "^5.1.0", | ||||||
|     "class-transformer": "^0.5.1", |     "class-transformer": "^0.5.1", | ||||||
|     "class-validator": "^0.14.0", |     "class-validator": "^0.14.0", | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ specifiers: | |||||||
|   '@prisma/client': ^4.10.1 |   '@prisma/client': ^4.10.1 | ||||||
|   '@types/bcrypt': ^5.0.0 |   '@types/bcrypt': ^5.0.0 | ||||||
|   '@types/express': ^4.17.13 |   '@types/express': ^4.17.13 | ||||||
|  |   '@types/jsonwebtoken': ^9.0.1 | ||||||
|   '@types/node': 18.11.18 |   '@types/node': 18.11.18 | ||||||
|   '@types/passport-jwt': ^3.0.8 |   '@types/passport-jwt': ^3.0.8 | ||||||
|   '@typescript-eslint/eslint-plugin': ^5.0.0 |   '@typescript-eslint/eslint-plugin': ^5.0.0 | ||||||
| @ -53,6 +54,7 @@ dependencies: | |||||||
|   '@nestjs/platform-express': 9.3.9_77foi4w27ghy47yutmnzv7krjy |   '@nestjs/platform-express': 9.3.9_77foi4w27ghy47yutmnzv7krjy | ||||||
|   '@nestjs/swagger': 6.2.1_ldzmua2hsw2tga2e42i6lmmdty |   '@nestjs/swagger': 6.2.1_ldzmua2hsw2tga2e42i6lmmdty | ||||||
|   '@prisma/client': 4.10.1_prisma@4.10.1 |   '@prisma/client': 4.10.1_prisma@4.10.1 | ||||||
|  |   '@types/jsonwebtoken': 9.0.1 | ||||||
|   bcrypt: 5.1.0 |   bcrypt: 5.1.0 | ||||||
|   class-transformer: 0.5.1 |   class-transformer: 0.5.1 | ||||||
|   class-validator: 0.14.0 |   class-validator: 0.14.0 | ||||||
|  | |||||||
| @ -4,9 +4,16 @@ import { AuthController } from './auth.controller' | |||||||
| import { PasswordService } from './password.service' | import { PasswordService } from './password.service' | ||||||
| import { JwtService } from '@nestjs/jwt' | import { JwtService } from '@nestjs/jwt' | ||||||
| import { JwtStrategy } from './strategies/jwt.strategy' | import { JwtStrategy } from './strategies/jwt.strategy' | ||||||
|  | import { EmailService } from 'src/email/email.service' | ||||||
| 
 | 
 | ||||||
| @Module({ | @Module({ | ||||||
|   controllers: [AuthController], |   controllers: [AuthController], | ||||||
|   providers: [AuthService, JwtService, JwtStrategy, PasswordService], |   providers: [ | ||||||
|  |     AuthService, | ||||||
|  |     JwtService, | ||||||
|  |     JwtStrategy, | ||||||
|  |     PasswordService, | ||||||
|  |     EmailService, | ||||||
|  |   ], | ||||||
| }) | }) | ||||||
| export class AuthModule {} | export class AuthModule {} | ||||||
|  | |||||||
| @ -10,7 +10,8 @@ import { Token, TokenPayload } from './dto/token.dto' | |||||||
| import { JwtService } from '@nestjs/jwt' | import { JwtService } from '@nestjs/jwt' | ||||||
| import { securityConfig, SecurityConfig } from 'src/common/configs' | import { securityConfig, SecurityConfig } from 'src/common/configs' | ||||||
| import { CreateUserDto } from 'src/users/dto/create-user.dto' | import { CreateUserDto } from 'src/users/dto/create-user.dto' | ||||||
| import { EmailSendDto } from 'src/email/dto/email.dto' | import { EmailSendDto, EmailScene } from 'src/email/dto/email.dto' | ||||||
|  | import { EmailService } from 'src/email/email.service' | ||||||
| 
 | 
 | ||||||
| @Injectable() | @Injectable() | ||||||
| export class AuthService { | export class AuthService { | ||||||
| @ -18,32 +19,28 @@ export class AuthService { | |||||||
|     private passwordService: PasswordService, |     private passwordService: PasswordService, | ||||||
|     private jwtService: JwtService, |     private jwtService: JwtService, | ||||||
|     private prismaService: PrismaService, |     private prismaService: PrismaService, | ||||||
|  |     private emailService: EmailService, | ||||||
|     @Inject(securityConfig.KEY) |     @Inject(securityConfig.KEY) | ||||||
|     private secureConfig: SecurityConfig, |     private secureConfig: SecurityConfig, | ||||||
|   ) {} |   ) {} | ||||||
| 
 | 
 | ||||||
|   async register(userToCreate: CreateUserDto) { |   async register(userToCreate: CreateUserDto) { | ||||||
|     console.log(userToCreate) |     const tokenPayload = this.jwtService.verify<EmailSendDto>( | ||||||
|     try { |       userToCreate.token, | ||||||
|       const tokenPayload = this.jwtService.verify<EmailSendDto>( |       { | ||||||
|         userToCreate.token, |         secret: this.emailService.getEmailJwtSecret( | ||||||
|         { |           userToCreate.verificationCode, | ||||||
|           secret: |           EmailScene.register, | ||||||
|             this.secureConfig.jwt_access_secret + |         ), | ||||||
|             userToCreate.verificationCode + |       }, | ||||||
|             'register', |     ) | ||||||
|         }, |     if ( | ||||||
|       ) |       tokenPayload.email !== userToCreate.email || | ||||||
|       if ( |       tokenPayload.scene !== 'register' | ||||||
|         tokenPayload.email !== userToCreate.email || |     ) { | ||||||
|         tokenPayload.scene !== 'register' |       throw new ForbiddenException('请输入正确的邮箱') | ||||||
|       ) { |  | ||||||
|         throw new ForbiddenException('请输入正确的邮箱') |  | ||||||
|       } |  | ||||||
|     } catch (err) { |  | ||||||
|       console.error(err) |  | ||||||
|       throw new ForbiddenException(err.message) |  | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     const hashedPassword = await this.passwordService.hashPassword( |     const hashedPassword = await this.passwordService.hashPassword( | ||||||
|       userToCreate.password, |       userToCreate.password, | ||||||
|     ) |     ) | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								src/common/filters/jwt-exceptions.filter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/common/filters/jwt-exceptions.filter.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | import { | ||||||
|  |   Catch, | ||||||
|  |   Logger, | ||||||
|  |   ArgumentsHost, | ||||||
|  |   ForbiddenException, | ||||||
|  | } from '@nestjs/common' | ||||||
|  | import { BaseExceptionFilter } from '@nestjs/core' | ||||||
|  | import { JsonWebTokenError } from 'jsonwebtoken' | ||||||
|  | 
 | ||||||
|  | @Catch(JsonWebTokenError) | ||||||
|  | export class JwtExceptionsFilter extends BaseExceptionFilter { | ||||||
|  |   private readonly logger = new Logger(JsonWebTokenError.name) | ||||||
|  | 
 | ||||||
|  |   catch(exception: JsonWebTokenError, host: ArgumentsHost) { | ||||||
|  |     this.logger.error(exception) | ||||||
|  |     super.catch(new ForbiddenException(exception.message), host) | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -33,5 +33,6 @@ import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handleba | |||||||
|   ], |   ], | ||||||
|   controllers: [EmailController], |   controllers: [EmailController], | ||||||
|   providers: [EmailService, JwtService], |   providers: [EmailService, JwtService], | ||||||
|  |   exports: [EmailService], | ||||||
| }) | }) | ||||||
| export class EmailModule {} | export class EmailModule {} | ||||||
|  | |||||||
| @ -36,20 +36,21 @@ export class EmailService { | |||||||
|     const verificationCode = this.generateRandomNum() |     const verificationCode = this.generateRandomNum() | ||||||
|     const registerToken = this.jwtService.sign( |     const registerToken = this.jwtService.sign( | ||||||
|       { email, scene }, |       { email, scene }, | ||||||
|       { |       { secret: this.getEmailJwtSecret(verificationCode, scene) }, | ||||||
|         secret: this.secureConfig.jwt_access_secret + verificationCode + scene, |  | ||||||
|         expiresIn: '30min', |  | ||||||
|       }, |  | ||||||
|     ) |     ) | ||||||
|     await this.mailerService.sendMail({ |     await this.mailerService.sendMail({ | ||||||
|       to: email, |       to: email, | ||||||
|       subject: '注册qiuxu.site', |       subject: '注册qiuxu.site', | ||||||
|       html: `您正在注册qiuxu.site,验证码为 <strong>${verificationCode}</strong>,30分钟内有效`, |       html: `您正在注册qiuxu.site,验证码为 <strong>${verificationCode}</strong>,30分钟内有效`, | ||||||
|     }) |     }) | ||||||
|     return { registerToken, verificationCode } |     return registerToken | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getEmailJwtSecret(verificationCode: string, scene: EmailScene) { | ||||||
|  |     return this.secureConfig.jwt_access_secret + verificationCode + scene | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private generateRandomNum() { |   private generateRandomNum() { | ||||||
|     return Math.floor(Math.random() * 899999 + 100000) |     return Math.floor(Math.random() * 899999 + 100000).toString() | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ import { ValidationPipe } from '@nestjs/common' | |||||||
| import { ConfigService } from '@nestjs/config' | import { ConfigService } from '@nestjs/config' | ||||||
| import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger' | import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger' | ||||||
| import { PrismaClientExceptionFilter, PrismaService } from 'nestjs-prisma' | import { PrismaClientExceptionFilter, PrismaService } from 'nestjs-prisma' | ||||||
|  | import { JwtExceptionsFilter } from './common/filters/jwt-exceptions.filter' | ||||||
| import { AppModule } from './app.module' | import { AppModule } from './app.module' | ||||||
| 
 | 
 | ||||||
| async function bootstrap() { | async function bootstrap() { | ||||||
| @ -18,6 +19,7 @@ async function bootstrap() { | |||||||
|   // Prisma Client Exception Filter for unhandled exceptions
 |   // Prisma Client Exception Filter for unhandled exceptions
 | ||||||
|   const { httpAdapter } = app.get(HttpAdapterHost) |   const { httpAdapter } = app.get(HttpAdapterHost) | ||||||
|   app.useGlobalFilters(new PrismaClientExceptionFilter(httpAdapter)) |   app.useGlobalFilters(new PrismaClientExceptionFilter(httpAdapter)) | ||||||
|  |   app.useGlobalFilters(new JwtExceptionsFilter(httpAdapter)) | ||||||
| 
 | 
 | ||||||
|   // Swagger Api
 |   // Swagger Api
 | ||||||
|   const options = new DocumentBuilder() |   const options = new DocumentBuilder() | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user