🔥🔥超简单!!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机制的登录已经完成了。

相关推荐
安冬的码畜日常1 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记2 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java2 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele2 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范
懒羊羊大王呀2 小时前
CSS——属性值计算
前端·css
DOKE3 小时前
VSCode终端:提升命令行使用体验
前端
xgq3 小时前
使用File System Access API 直接读写本地文件
前端·javascript·面试
用户3157476081353 小时前
前端之路-了解原型和原型链
前端
永远不打烊3 小时前
librtmp 原生API做直播推流
前端