NestJS简明教程——安全

登录和注册(代码示例)

需要安装的依赖

bash 复制代码
pnpm add @nestjs/jwt @nestjs/throttler helmet  

auth.service.ts

ts 复制代码
import {
  ConflictException,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { UsersService } from '../users/users.service';
import * as bcrypt from 'bcrypt';
import { SignUpDto } from './dto/sign-up.dto';
import { SignInDto } from './dto/sign-in.dto';
import { NotFoundError } from '@mikro-orm/core';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(
    private readonly usersService: UsersService,
    private readonly jwtService: JwtService,
  ) {}

  async generateToken(user: any): Promise<{ access_token: string }> {
    const payload = { email: user.email, sub: user.id };
    return {
      access_token: await this.jwtService.signAsync(payload),
    };
  }

  async signUp(signUpDto: SignUpDto): Promise<any> {
    const { email, name, password } = signUpDto;

    const user = await this.usersService.findOne(email);
    if (user) {
      throw new ConflictException('User already exists');
    }

    const hashedPassword = await bcrypt.hash(password, 10);

    await this.usersService.create({ email, name, password: hashedPassword });

    return await this.usersService.findOne(email);
  }

  async signIn(signInDto: SignInDto): Promise<any> {
    const { email, password } = signInDto;

    const user = await this.usersService.findOne(email);
    if (!user) {
      throw new NotFoundError('User not found');
    }

    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      throw new UnauthorizedException('Invalid password');
    }

    const token = await this.generateToken(user);

    return { user, token };
  }
}

auth.controller.ts

ts 复制代码
import { Controller } from '@nestjs/common';
import { AuthService } from './auth.service';
import { Post, Body } from '@nestjs/common';
import { SignUpDto } from './dto/sign-up.dto';
import { SignInDto } from './dto/sign-in.dto';
import { Public } from './decorator/public.decorator';

@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @Post('register')
  @Public()
  async signUp(@Body() signUpDto: SignUpDto): Promise<any> {
    return this.authService.signUp(signUpDto);
  }

  @Post('login')
  @Public()
  async signIn(@Body() signInDto: SignInDto): Promise<any> {
    return this.authService.signIn(signInDto);
  }

}

auth.module.ts

ts 复制代码
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { UsersModule } from '../users/users.module';
import { JwtModule } from '@nestjs/jwt';
import { APP_GUARD } from '@nestjs/core';
import { AuthGuard } from './auth.guard';

@Module({
  imports: [
    UsersModule,
    JwtModule.register({
      secret: process.env.JWT_SECRET,
      signOptions: { expiresIn: '1h', algorithm: 'HS256' },
    }),
  ],
  providers: [
    AuthService,
    {
      provide: APP_GUARD,
      useClass: AuthGuard,
    },
  ],
  controllers: [AuthController],
})
export class AuthModule {}

JWT

auth.guard.ts

bash 复制代码
nest g guard auth/auth --no-spec --flat
ts 复制代码
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Reflector } from '@nestjs/core';
import { IS_PUBLIC_KEY } from './decorator/public.decorator';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private readonly jwtService: JwtService,
    private reflector: Reflector,
  ) {}

  private extractTokenFromHeader(request: any): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {

    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
    ]);
    if (isPublic) {
      // 💡 See this condition
      return true;
    }

    // get the request object from the execution context
    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);

    if (!token) {
      throw new UnauthorizedException('No token provided');
    }

    // verify the token using the JwtService
    try {
      const payload = await this.jwtService.verifyAsync(token);
      request['user'] = payload;
    } catch (error) {
      throw new UnauthorizedException('Invalid token');
    }

    return true;
  }
}

public.decorator.ts

bash 复制代码
nest g decorator auth/decorator/public --flat
ts 复制代码
import { SetMetadata } from '@nestjs/common';

export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);

限流

app.module.ts

ts 复制代码
import { ThrottlerModule } from '@nestjs/throttler';
import throttlerConfig from './common/config/c';
ThrottlerModule.forRoot(throttlerConfig)

throttler.config.ts

复制代码
export default [
  {
    name: 'short',
    ttl: 1000,
    limit: 3,
  },
  {
    name: 'medium',
    ttl: 10000,
    limit: 20,
  },
  {
    name: 'long',
    ttl: 60000,
    limit: 100,
  },
];

其他

helmet

main.ts

ts 复制代码
// 加入 Helmet 中间件以增强安全性
  app.use(helmet());
相关推荐
Raas10020 小时前
MAI Gateway (魔芋企业级AI网关)支持哪些模型?AI网关多模型统一接入实战指南
人工智能·安全·gateway·企业级·ai网关
君顾121 小时前
智慧场馆解决方案小程序系统开发实战指南
java·开发语言·智慧场馆
爱酱丶21 小时前
VS Code 快速生成Vue3 + TypeScript + Setup 基础空模板
前端·javascript·typescript
Maxkim21 小时前
在 GitHub 仓库里配一个 AI Code Reviewer,自动审查 PR
前端·javascript
运维行者_21 小时前
预测性云监控怎么做?AI驱动的7大核心能力与落地路径
服务器·开发语言·网络·数据库·人工智能·python·php
NeverSettle_21 小时前
Agent 如何快速调用公司接口?——CLI + Skill 实践与踩坑
前端·javascript·后端
sugar__salt21 小时前
三列布局与 TypeScript 工具类型 Pick / Omit / Partial 详解
前端·javascript·typescript
名字还没想好☜21 小时前
Next.js Route Handler 做 SSE 服务端推送:实时进度条、自动重连与什么时候别用 WebSocket
开发语言·javascript·websocket·react·sse·next.js
进制树21 小时前
【飞控开发实战·㉒】ROS2无人机应用开发实战:Offboard控制、航点任务、AprilTag降落与避障系统
开发语言·安全·无人机·课程设计
江畔柳前堤21 小时前
LLM + Agent 模型效果评估:从入门到工业级体系构建的完整指南
开发语言·人工智能·自然语言处理·chatgpt·架构·json·batch