什么是jwt?
JWT(JSON Web Token)是一种开放的标准(RFC 7519),用于在网络应用间传递信息的一种方式。它是一种基于JSON的安全令牌,用于在客户端和服务器之间传输信息。 https://jwt.io/
JWT由三部分组成,它们通过点(.)进行分隔:
- Header(头部):包含了令牌的类型和使用的加密算法等信息。通常采用Base64编码表示。
- Payload(负载):包含了身份验证和授权等信息,如用户ID、角色、权限等。也可以自定义其他相关信息。同样采用Base64编码表示。
- Signature(签名):使用指定的密钥对头部和负载进行签名,以确保令牌的完整性和真实性。
JWT的工作流程如下:
- 用户通过提供有效的凭证(例如用户名和密码)进行身份验证。
- 服务器验证凭证,并生成一个JWT作为响应。JWT包含了用户的身份信息和其他必要的数据。
- 服务器将JWT发送给客户端。
- 客户端在后续的请求中,将JWT放入请求的头部或其他适当的位置。
- 服务器在接收到请求时,验证JWT的签名以确保其完整性和真实性。如果验证通过,服务器使用JWT中的信息进行授权和身份验证。
用到的依赖
passport
passport是一个流行的用于身份验证和授权的Node.js库passport-jwt
Passport-JWT是Passport库的一个插件,用于支持使用JSON Web Token (JWT) 进行身份验证和授权jsonwebtoken
生成token的库
代码编写
沿用上一章的代码 增加jwt目录
上一章代码
src/jwt/index.ts
import { injectable } from 'inversify'
import jsonwebtoken from 'jsonwebtoken'
import passport from 'passport'
import { Strategy, ExtractJwt } from 'passport-jwt'
@injectable()
export class JWT {private secret = 'xiaoman$%^&*()asdsd'private jwtOptions = {jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),secretOrKey: this.secret}constructor() {this.strategy()}/*** 初始化jwt*/public strategy() {const strategy = new Strategy(this.jwtOptions, (payload, done) => {done(null, payload)})passport.use(strategy)}/*** * @returns 中间件*/public middleware() {return passport.authenticate('jwt', { session: false })}/*** 创建token* @param data Object*/public createToken(data: object) {//有效期为7天return jsonwebtoken.sign(data, this.secret, { expiresIn: '7d' })}/*** * @returns 集成到express*/public init() {return passport.initialize()}
}
main.ts
import 'reflect-metadata'
import { InversifyExpressServer } from 'inversify-express-utils'
import { Container } from 'inversify'
import { User } from './src/user/controller'
import { UserService } from './src/user/services'
import express from 'express'
import { PrismaClient } from '@prisma/client'
import { PrismaDB } from './src/db'
import { JWT } from './src/jwt'
const container = new Container()
/*** user模块*/
container.bind(User).to(User)
container.bind(UserService).to(UserService)
/*** 封装PrismaClient*/
container.bind<PrismaClient>('PrismaClient').toFactory(() => {return () => {return new PrismaClient()}
})
container.bind(PrismaDB).to(PrismaDB)
/*** jwt模块*/
container.bind(JWT).to(JWT) //主要代码const server = new InversifyExpressServer(container)
server.setConfig((app) => {app.use(express.json())app.use(container.get(JWT).init()) //主要代码
})
const app = server.build()app.listen(3000, () => {console.log('Listening on port 3000')
})
src/user/controller.ts
import { controller, httpGet as GetMapping, httpPost as PostMapping } from 'inversify-express-utils'
import { UserService } from './services'
import { inject } from 'inversify'
import type { Request, Response } from 'express'
import { JWT } from '../jwt'
const {middleware} = new JWT()
@controller('/user')
export class User {constructor(@inject(UserService) private readonly UserService: UserService) {}@GetMapping('/index',middleware()) //主要代码public async getIndex(req: Request, res: Response) {let result = await this.UserService.getList()res.send(result)}@PostMapping('/create')public async createUser(req: Request, res: Response) {let result = await this.UserService.createUser(req.body)res.send(result)}
}
src/user/services.ts
import { injectable, inject } from 'inversify'
import { PrismaDB } from '../db'
import { UserDto } from './user.dto'
import { plainToClass } from 'class-transformer'
import { validate } from 'class-validator'
import { JWT } from '../jwt'
@injectable()
export class UserService {constructor(@inject(PrismaDB) private readonly PrismaDB: PrismaDB,@inject(JWT) private readonly jwt: JWT //依赖注入) {}public async getList() {return await this.PrismaDB.prisma.user.findMany()}public async createUser(user: UserDto) {let userDto = plainToClass(UserDto, user)const errors = await validate(userDto)if (errors.length) {return errors} else {const result = await this.PrismaDB.prisma.user.create({data: user})return {...result,token: this.jwt.createToken(result) //生成token}}}
}
哪个接口需要token验证就往哪儿加就可以了
- 验证失败展示(未携带token)
- 验证成功展示(携带token)