JWT
JWT(JSON Web Token)是一种开放的标准(RFC 7519),一种用于在网络应用间传递信息的方式
它是一种基于JSON的安全令牌,用于在客户端和服务器之间传输信息
JWT的组成
JWT由三部分组成,它们通过点(.)进行分隔
- Header(头部):包含令牌的类型、使用的加密算法等信息,常用Base64编码表示
- Payload(负载):包含身份验证和授权等信息,如用户ID、角色、权限等,也可以自定义其他相关信息,同样采用Base64编码表示
- Signature(签名):使用指定密钥对头部和负载进行签名,以确保令牌的完整性和真实性
JWT的工作流程
- 用户通过提供有效的凭证(例如用户名和密码)进行身份验证
- 服务器验证凭证,并生成一个JWT作为响应,JWT包含了用户的身份信息和其他必要的数据
- 服务器将JWT发送给客户端
- 客户端在后续的请求中,将JWT放入请求的头部或其他适当的位置
- 服务器在接收到请求时,验证JWT的签名以确保其完整性和真实性,如果验证通过,服务器使用JWT中的信息进行授权和身份验证
使用
依赖
- passport:用于身份验证和授权
- passport-jwt:是passport库的一个插件,用于支持使用JWT进行身份验证和授权
- jsonwebtoken:生成token
1
| pnpm i passport passport-jwt jsonwebtoken @types/passport @types/passport-jwt @types/jsonwebtoken
|
代码
在src/jwt/index.ts编写jwt类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import { injectable } from "inversify" import passport from 'passport' import jsonwebtoken from 'jsonwebtoken' import { Strategy, ExtractJwt } from 'passport-jwt'
@injectable() export class JWT {
private secret = 'yajuesenpai114514' private jwtOptions = { jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: this.secret }
constructor() { this.strategy() }
public strategy () { let strategy = new Strategy(this.jwtOptions, (payload, done) => { done('成功了', payload) }) passport.use(strategy) }
static middleware () { return passport.authenticate('jwt', { session: false }) }
public createToken (data: object) { jsonwebtoken.sign({}, this.secret, { expiresIn: '7d' }) }
public init () { return passport.initialize() } }
|
在main.ts引入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| import 'reflect-metadata' import { InversifyExpressServer } from 'inversify-express-utils' import { Container } from 'inversify' import express from 'express'
import { PrismaClient } from '@prisma/client' import { PrismaDB } from './src/db'
import { JWT } from './src/jwt'
import { User } from './src/user/controller' import { UserService } from './src/user/service'
const container = new Container()
container.bind(User).to(User) container.bind(UserService).to(UserService)
container.bind<PrismaClient>(PrismaClient).toFactory(()=> { return ()=> { return new PrismaClient() } }) container.bind(PrismaDB).to(PrismaDB)
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(11451, ()=> { console.log('server on 11451') })
declare global { namespace Express { interface User { id: number, name: string, email: string } } }
|
在src/user/service.ts生成token:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import { injectable, inject } from "inversify" import { PrismaDB } from "../db"
import { plainToClass } from 'class-transformer' import { validate } from 'class-validator' import { UserDto } from "./user.dto"
import { JWT } from "../jwt" import { INJECT_TAG } from "inversify/lib/constants/metadata_keys"
@injectable() export class UserService {
constructor( @inject(PrismaDB) private readonly PrismaDB:PrismaDB, @inject(JWT) private readonly jwt:JWT ) { }
public async createUser(user: UserDto) { const 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) } } } }
|
在src/user/controller.ts验证token:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import { controller, httpGet as Get, httpPost as Post } from "inversify-express-utils" import { UserService } from "./service" import { inject } from "inversify" import type { Request, Response } from "express"
import { JWT } from "../jwt"
@controller('/user') export class User {
constructor(@inject(UserService) private readonly userService: UserService) { }
@Get('/index', JWT.middleware()) public async getIndex(req: Request, res: Response) { console.log(req.user.id) let result = await this.userService.getList() res.send(result) }
}
|