前言

jwt生成,nestjs官方有一个专门的库@nestjs/jwt,它是一个模块,我们只需要将他注册为全局模块,并且传入secret密匙就能直接去使用它的服务了。

教程

先安装依赖:

pnpm i @nestjs/jwt

在app.module.ts中引入该模块,通过useFactory工厂模式,获取到ConfigModule提供的ConfigService服务,从而拿到环境变量文件中配置的secret

.env.development

在环境变量中配置TOKEN_SECRET

# token-secret
TOKEN_SECRET="xxxxx"

注意不要泄露这个密匙。

app.module.ts

import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { AuthModule } from "./auth/auth.module";
import { PrismaModule } from "./prisma/prisma.module";
import { JwtModule } from "@nestjs/jwt";



const NODE_ENV = process.env.NODE_ENV;

@Module({
    imports: [
        ConfigModule.forRoot({
            isGlobal: true,
            envFilePath: NODE_ENV === "development" ? ".env.development" : `.env.${NODE_ENV}`
        }),
        PrismaModule,
        JwtModule.registerAsync({
            global: true,
            inject: [ConfigService],
            useFactory: (configService: ConfigService) => {
                return {
                    secret: configService.get("TOKEN_SECRET"),
                    signOptions: {
                        expiresIn: "30d"
                    }
                };
            }
        }),
        AuthModule
    ],
    controllers: [],
    providers: []
})
export class AppModule {}

由于我们需要先等待ConfigModule加载到环境变量,所以我们使用异步注册的方法registerAsync,传入配置选项:

  1. global,注册成全局模块,方便其他地方使用。
  2. inject,注入需要的服务,由于ConfigModule已经设置成全局了,就不需要单独再JwtModuleimports: [ConfigModule]声明依赖了,只需要注入服务即可。
  3. useFactory,工厂函数,形参为注入的服务。
  4. expiresIn表示过期时间,具体其他配置可以查看jsonwebtoken文档:文档,该插件依赖了jsonwebtoken这个库。

现在我们已经加载完成依赖,下面开始使用。

使用

import { BadRequestException, Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { RegisterDto } from "./dto/register.dto";
import { LoginDto } from "./dto/login.dto";
import { PrismaService } from "src/prisma/prisma.service";
import { hash, verify } from "../utils/md5";
import { JwtService } from "@nestjs/jwt";
import type { user } from "@prisma/client";

@Injectable()
export class AuthService {
    constructor(
        private readonly prisma: PrismaService,
        private readonly config: ConfigService,
        private readonly jwtService: JwtService
    ) {}

    /** 注册账号 */
    async register(data: RegisterDto) {
        const { email, password } = data;
        const md5Salt: string = this.config.get("MD5_SALT");
        const user = await this.prisma.user.create({
            data: {
                email,
                password: hash(password, md5Salt)
            }
        });

        return this.generateToken(user);
    }

    /** 登录 */
    async login(data: LoginDto) {
        const { email, password } = data;
        const md5Salt: string = this.config.get("MD5_SALT");

        // 查找用户
        const findUser = await this.prisma.user.findFirst({
            where: {
                email
            }
        });

        // 比对密码
        if (!verify(password, findUser.password, md5Salt)) {
            throw new BadRequestException("密码错误");
        }

        return this.generateToken(findUser);
    }

    /** 生成token */
    private async generateToken({ id, email }: user) {
        return {
            token: await this.jwtService.signAsync({
                sub: id,
                email: email
            })
        };
    }
}

注入JwtService服务,它提供了两种生成方式,一种异步的signAsync,一种是同步的sign方式,看自己需要使用。

jwt的规范中,载荷(Payload)中规定有一个sub字段,用于表示主要内容,这里我们的用户id就是主要内容,后续查询用户都是需要用到这个,所以id被赋值给了sub属性,然后自定义了一个email字段。

此时我们的token也可以正常生成了。

分类: Nest.js 标签: tokenNestjs@nestjs/jwt

评论

暂无评论数据

暂无评论数据

目录