🔥🔥超简单!!nestJS+jwt实现登录

创建项目

1、在命令行输入nest new jwt-login,jwt-login是项目名。回车键继续。

2、选择包管理工具,这里我选择npm,回车键继续

此时就开始安装依赖包了,这里要等一等

进入项目就会看到这样的目录
3、控制台输入npm run start:dev启动项目, 出现这样的情况就是启动成功了。

端口号默认是3000,在浏览器输入http://localhost:3000, 出现hello word就是启动成功了

实现登录功能

创建auth模块

在浏览器输入nest g res auth --no-spec

默认选择rest api 一直回车,此时目录出现了auth文件夹

数据传输对象(dto)

在auth/dto/中将创建login-auth.dto.ts,并添加如下代码:

ts 复制代码
export class LoginAuthDto {
  username: string;
  password: string;
}

显然所谓的数据传输对象就是前端传递过来的参数对象,这里前端需要传递username和password,那么为什么要创建这个数据传输对象呢,继续往下看。

安装依赖包:npm i --save class-validator class-transformer,接着将login-auth.dto.ts中的代码修改如下:

ts 复制代码
import { IsNotEmpty, Length } from 'class-validator';
export class LoginAuthDto {
  @IsNotEmpty({ message: 'Username is required' })
  username: string;

  @IsNotEmpty({ message: 'Password is required' })
  @Length(6, 20, { message: 'Password must be between 6 and 20 characters' })
  password: string;
}

以上代码中增加了两个装饰器,很显然一个是@IsNotEmpty的装饰器是校验该项不能为空的,@Leng是来限制参数的长度的。这个dto对象该如何用呢,后面继续会讲到。

在main.ts中新增如下代码:

ts 复制代码
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();

以上新增的代码意思是全局启用管道验证,具体功效后面会讲到。

创建登录接口

在auth/auth.service.ts中将原用自动生成的函数删掉,新增login函数:

ts 复制代码
import { Body, Controller, Post } from '@nestjs/common';
import { AuthService } from './auth.service';
import { LoginAuthDto } from './dto/login-auth.dto';

@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) {}
  @Post('login')
  login(@Body() loginAuthDto: LoginAuthDto) {
    return loginAuthDto;
  }
}

注意login函数中的参数使用了之前创建的LoginAuthDto对象,在这里可以对前端传来的参数进行校验。

在apifox里面进行测试:

username设置为空的情况下请求会返回我们之前定义的报错信息,如果把username补上去就是这样的:

可见已经跑通了。这就是dto的魅力所在,可以很简单的实现参数的校验。

jwt

配置jwt

一般来说正常的登录逻辑是前端传递过来username和password后端生成token返回给前端,前端之后在请求头里面带上token。

安装依赖包:npm install --save @nestjs/jwt。在app.module.ts中引入配置jwt:

ts 复制代码
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
import { JwtModule } from '@nestjs/jwt';

@Module({
  imports: [
    AuthModule,
    JwtModule.register({
      global: true,
      secret: 'xiaosong',
      signOptions: { expiresIn: '7d' },
    }),
  ],

  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

global: 将JwtModule设置成全局模块,secret:密钥,用于JWT令牌的签名和验证,signOptions: 设置token的过期时间为7天。

生成token

在auht/auth.service.ts中增加login函数,并且将自动生成的代码删除掉:

ts 复制代码
import { HttpException, Injectable } from '@nestjs/common';
import { LoginAuthDto } from './dto/login-auth.dto';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(private readonly jwtService: JwtService) {}
  login(loginAuthDto: LoginAuthDto) {
    const user = {
      id: 1,
      username: 'xiaosong',
      password: '123123',
    };

    if (
      loginAuthDto.username !== user.username ||
      loginAuthDto.password !== user.password
    ) {
      throw new HttpException('用户名或密码错误', 401);
    }

    return {
      token: this.jwtService.sign({
        id: user.id,
        username: user.username,
      }),
    };
  }
}

以上代码看似很多其实很简单,user对象模拟的数据库,存储了用户名、密码、id,当username和password有一处不对的时候抛出异常否则就使用sign生成token,并且token里面携带的是id和username。注意constructor构造函数中是依赖注入,将jwtService这个对象注入进来。

在auth.controller.ts中的login函数中将代码修改一下:

ts 复制代码
import { Body, Controller, Post } from '@nestjs/common';
import { AuthService } from './auth.service';
import { LoginAuthDto } from './dto/login-auth.dto';

@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) {}
  @Post('login')
  login(@Body() loginAuthDto: LoginAuthDto) {
    return this.authService.login(loginAuthDto);
  }
}

在apifox里测试一下,先试一试密码不正确的情况: 看到返回了报错信息

再次试一下都正确的情况:

ok,可以看到返回token了

token校验

创建守卫

生成token了但是不进行校验就是虚空的token,这里要创建一个守卫进行拦截

执行指令:nest g gu login 创建一个守卫,在login/login.gurad.ts中增加如下代码

ts 复制代码
import {
  CanActivate,
  ExecutionContext,
  HttpException,
  Injectable,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { Request } from 'express';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class LoginGuard implements CanActivate {
  constructor(private jwtService: JwtService) {}
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request: Request = context.switchToHttp().getRequest();
    const token = request.headers.authorization;

    try {
      this.jwtService.verify(token, {
        secret: 'xiaosong',
      });
    } catch (error) {
      throw new HttpException('token失效', 401);
    }

    return true;
  }
}

以上代码看似十分的复杂,其实核心代码如下:

  • context.switchToHttp().getRequest();:获取request对象
  • request.headers.authorization;:获取token
  • this.jwtService.verify(token, {secret: 'xiaosong',});:token校验

使用守卫

在auth.controller.ts中随便加一个接口

以上代码的 @UseGuards(LoginGuard)是使用创建的login守卫

在apifox里面测试一下:

可见报错了,守卫生效了

先登录获取token,在请求头加上token再试一下:

ok,请求通过了,可见我们的守卫也是十分的好用的。至此jwt机制的登录已经完成了。

相关推荐
Live000001 分钟前
在鸿蒙中使用 Repeat 渲染嵌套列表,修改内层列表的一个元素,页面不会更新
前端·javascript·react native
柳杉2 分钟前
使用Ai从零开发智慧水利态势感知大屏(开源)
前端·javascript·数据可视化
兆子龙12 分钟前
从高阶函数到 Hooks:React 如何减轻开发者的心智负担(含 Demo + ahooks 推荐)
前端
狗胜17 分钟前
测试文章 - API抓取
前端
三小河17 分钟前
VS Code 集成 claude-code 教程:告别海外限制,无缝对接国内大模型
前端·程序员
jerrywus22 分钟前
前端老哥的救命稻草:用 Obsidian 搞定 Claude Code 的「金鱼记忆」
前端·agent·claude
球球pick小樱花27 分钟前
游戏官网前端工具库:海内外案例解析
前端·javascript·css
用户605723748730835 分钟前
AI 编码助手的规范驱动开发 - OpenSpec 初探
前端·后端·程序员
狗胜38 分钟前
AI观察日记 2026-03-02|CLAUDE、TYPE、APPFUNCTIONS:掘金热门里的下一步信号
前端