在 Nest.js 中使用JWT

273 阅读2分钟

在接口调用中,我们经常会遇到需要用户登录的情况,这时候一般比较常用的就是 jwt 了。在 nest 中,可以使用 nest 提供的 jwt 模块来实现 jwt 的功能。来看看如何使用吧。

安装

npm install @nestjs/jwt

引入 JwtModule 模块

我们需要在 app.module.ts 中引入 JwtModule 模块

register 方法接收一个对象,对象中有两个属性,一个是 secret,一个是 signOptions。secret 是用来加密的,signOptions 是用来设置 token 的过期时间的。在这里我们设置了 7 天过期。

import { Module } from '@nestjs/common'
import { JwtModule } from '@nestjs/jwt'
import { AppController } from './app.controller'
import { AppService } from './app.service'

@Module({
  imports: [
    JwtModule.register({
      secret: 'water',
      signOptions: {
        expiresIn: '7d'
      }
    })
  ],
  controllers: [AppController],
  providers: [AppService]
})
export class AppModule {}

使用 JwtService 生成token

import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common'
import { AppService } from './app.service'
import { JwtService } from '@nestjs/jwt'

@Controller()
export class AppController {
  constructor(private readonly appService: AppService, private readonly jwtService: JwtService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello()
  }

  @Post('login')
  login(@Body() body) {
    const token = this.jwtService.sign({
      username: body.username,
      password: body.password
    },{ secret: 'water' })// secret: 'water' 密钥
    return {
      token
    }
  }
}

使用验证 token

在接口调用的过程中,带上上面生成的 token,然后在控制器中使用 jwtService 的 verify 方法来验证 token

用 UseGuards 装饰器来使用 jwt 的验证,AuthGuard 的参数是 jwt,表示使用 jwt 的验证。然后在 getProfile 方法中使用 @Request() req 来获取用户信息。

import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common'
import { AppService } from './app.service'
import { JwtService } from '@nestjs/jwt'
import { AuthGuard } from './auth/auth.guard';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService, private readonly jwtService: JwtService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello()
  }

  @Post('login')
  login(@Body() body) {
    const token = this.jwtService.sign({
      username: body.username,
      password: body.password
    })
    return {
      token
    }
  }

  @Get('profile')
  getProfile(@Req() request) {
    const authHeader = request.headers.authorization;
    if(authHeader){
      try {
        const user = this.jwtService.verify(authHeader)
        return user;
      } catch (error) {
        return '请登录';
      }
    }
    return '请登录';
  }

  @Get('profile2')
  @UseGuards(AuthGuard)
  getProfile2(@Req() request) {
    console.log(request.user)
    return request.user;
  }
}

AuthGuard ./auth/auth.guard 类的源码

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private readonly jwtService: JwtService) {}
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest()
    const authHeader = request.headers.authorization
    if (!authHeader) {
      request.user = null
    }
    try {
      const user = this.jwtService.verify(authHeader)
      request.user = user
      return true
    } catch (error) {
      request.user = null
    }
  }
}

app.module.ts 引入 AuthGuard

providers: [...,AuthGuard],