前言
JWT 是什么
JWT (JSON Web Token) 是一个开放标准,它定义了一种以紧凑和自包含的方法,用于在双方之间安全地传输编码为 JSON 对象的信息。
因此,简单来说,它是 JSON 格式的加密字符串,其中包含敏感信息,它使我们能够验证不同服务间的发送者。
应该在什么时候使用 JWT?
授权: 这是使用 JWT 最常见的场景。JWT 用于授权而非身份验证。通过身份验证,我们验证用户名和密码是否有效,并将用户登录到系统中。通过授权,我们可以验证发送到服务器的请求是否属于通过身份验证登录的用户,从而可以授予该用户访问系统的权限,继而批准该用户使用获得的 token 访问路由、服务和资源。
信息交换: JSON Web Token 是在双方之间安全地传输信息的一种好方法。因为 JWT 可以被签名(例如,使用公钥/私钥对),所以使您能确保发送方是他们所声称的那一方。此外,由于签名是使用 Header 和 Payload 计算的,因此还使您能验证发送的内容没有被篡改。
在nest.js中使用
首先要导入第三方包
pnpm add @nestjs/passport passport passport-local @nestjs/jwt passport-jwt @nestjs/config pnpm add @types/passport-local @types/passport-jwt -D
获取token
接着在我们写身份验证的模块引入
JwtModule.registerAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (config: ConfigService) => { return { secret: config.get('TOKEN_SECRET'), signOptions: { expiresIn: '100h' } } } })
config这里引用的是configModule里面的服务,主要是读取环境变量,我们这里的Token密钥放在.env文件里面,详情看我之前环境变量配置那个博客
接着在app.module.ts中注册,这一步很关键,我做的时候一直报错,发现没有给我主动注入,需要手动注入
之后我们在auth.service.ts中使用这个服务类
这边我写的是prisma一个orm操作数据库,我们希望当我们登录验证通过之后会给我们返回一个token, token这个函数里面配置的是生成token的类型,我们根据id以及name的唯一性,生成的token也具有唯一性, 第二个配置需要给一个密钥,给我们的token密钥即可 ,接着我们发送一下登录的请求
发现已经拿到token了,接下来我们就是根据token来获取对应用户的信息
接着我们在apifox中配置一下,将我们的token收集起来
这样配置好之后后续请求就可以带上token了
用token进行身份验证
我们需要创建一个验证策略 这个用的这个包的使用 nestjs-local-jwt-strategy - npm (npmjs.com)
import { ExtractJwt, Strategy } from 'passport-jwt'; import { PassportStrategy } from '@nestjs/passport'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { PrismaService } from '../prisma/prisma.service'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { constructor( config: ConfigService, private readonly prisma: PrismaService ) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: config.get('TOKEN_SECRET'), }); } async validate({ sub: id }) { return await this.prisma.user.findUnique({ where: { id } }) } }
super的第一个参数表示,当我们请求时,可以自动获取头里面包含的token,第二个就是token密钥了,当我们上述步骤都没问题时开始走下面的验证规则 我这里是分析出token里面的id信息,然后去找到数据库里对应的信息 要注意这里返回的东西会挂在到一个全局对象requset身上,就跟我们在前端的window对象一样,所以我们后续可以取到我们想要的那个用户的信息了
/* eslint-disable prettier/prettier */ import { Controller, Post, Body, Get, UseGuards, Req } from '@nestjs/common'; import { AuthService } from './auth.service'; import RegisterDto from '../dto/register.dto'; import LoginDto from '../dto/login.dto'; import { AuthGuard } from '@nestjs/passport'; import { Request } from 'express'; @Controller('auth') export class AuthController { constructor(private readonly auth: AuthService, ) { } @Post('register') register(@Body() dto: RegisterDto) { return this.auth.register(dto); } @Post('login') login(@Body() dto: LoginDto) { return this.auth.login(dto) } @Get('all') @UseGuards(AuthGuard('jwt')) all(@Req() req: Request) { return req.user } }
接着在controller中我们用上守卫把验证策略用上 这里的'jwt'是跟这里一样
这样我们就拿到了对应token的用户信息
写在最后
jwt的内容不多,但是是开发中最常见的应用场景了,多加练习,才能真正掌握,现在框架基本都是面向扩展包开发了,多看看常用包的文档,提高开发效率。最后,写的不好的地方欢迎大家批评指正,希望大家能有所收获!