NestJS使用Jwt实现登录功能

1,678 阅读3分钟

开发背景

在前面两天的文章中,介绍了一下注册功能,这里来回顾一下。

需要后端两个接口:

  • 获取邮箱验证码(参数:邮箱验证码类型)
  • 注册(参数:邮箱验证码密码)

主要流程是:

  1. 用户点击获取验证码按钮(自定义指令v-countdown)调用获取验证码接口
  2. 后端调用封装的Email类发送验证码
  3. 用户收到验证码
  4. 调用注册接口
  5. 后端先校验除验证码外的其他参数
  6. 校验无问题调用Redis类读取获取到的验证码
  7. 开始校验验证码
  8. 验证码校验无问题调用实体的save方法将用户信息保存到用户表
  9. 调用Redis类手动删除该验证码
  10. 反馈给用户注册成功

回顾完注册流程之后,这篇文章来聊一聊登录流程。

登录仅需要一个接口,该接口接收两个参数,邮箱密码,成功之后给前端返回token信息。本篇内容不讲接口的实现,重点放在Jwt生成与校验token

开始开发

Jwt介绍

一个 JWT 实际上就是一个字符串,它由三部分组成,头部载荷签名。前两部分需要经过 Base64 编码,后一部分通过前两部分 Base64 编码后再加密而成,是前后端分离之后比较通用的一种鉴权方案。

安装依赖

这里我使用的是NestJS开发的后端服务,就来安装nestjs对应的jwt插件。

npm i @nestjs/jwt @nestjs/passport passport-jwt

配置文件

这里我们有一个配置文件,假设是src/config/index.ts

export default {
  // ...
  JwtConfig: {
    secret: 'webxue',
    signOptions: { expiresIn: '60s' },
  },
}

这个配置文件导出了Jwt的配置信息JwtConfig,其中secret指的是一个字符串,用来进行token的加密,singnOptions是个对象,expiresIn指的是token过期时间。

注入Jwt

需要将jwt注入到我们的modules中,这里我是在api.module.ts中注入。

import { JwtModule } from '@nestjs/jwt';
import { JwtConfig } from 'src/config';

@Module({
  // 在这里引入
  imports: [JwtModule.register(JwtConfig)],
  // ...
})
export class ApiModule {}

然后在src/common/strategy定义Jwt策略jwt.strategy.ts

import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";
import { JWT_CONFIG } from "src/config";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      // 分别传入这些参数
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: JWT_CONFIG.secret,
    });
  }

  // token校验成功,会走到这里,否则会直接走401
  async validate(payload: any) {
    return payload;
  }
}

然后将策略注入到api.module.ts中:

import { JwtStrategy } from "src/common/strategy/jwt.strategy";

// ...
@Module({
  imports: [JwtModule.register(JWT_CONFIG)],
  providers: [
    // ...
    JwtStrategy,
  ],
})

生成token

在我们的登录service内定义jwtService

import { JwtService } from "@nestjs/jwt";

@Injectable()
export class AuthService extends BaseService {
  constructor(
    // 定义jwtService
    private jwtService: JwtService,
  ) {
    super();
  }

最后在登录接口内根据用户传入的emailpassword,与数据库中的数据进行对比,如果校验成功了,则通过下述代码就可以生成token了:

const token = this.jwtService.sign(userInfo);

结语

我本是一名前端程序员,但不甘于前端,最开始学习nodejs时使用的express,尽管以前使用jsonwebtoken插件做过生成校验token,但通过nestjs是第一次实现,如果哪里有什么不妥当的地方,还请大家评论指正,有讨论才有进步。最后,感谢大家能看到此处!