feat: table scan to delete outdate token
Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
@@ -59,7 +59,7 @@ export const AXIOS_CONFIG: AxiosRequestConfig = {
|
||||
|
||||
export const SECURITY = {
|
||||
jwtSecret: argv.jwt_secret || argv.jwtSecret,
|
||||
jwtExpire: '7d',
|
||||
jwtExpire: +argv.jwt_expire || 14,
|
||||
// 跳过登陆鉴权
|
||||
skipAuth: isTest ? true : false,
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import cluster from 'cluster'
|
||||
import dayjs from 'dayjs'
|
||||
import { sign, verify } from 'jsonwebtoken'
|
||||
import { machineIdSync } from 'node-machine-id'
|
||||
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { Injectable, Logger } from '@nestjs/common'
|
||||
import { CronExpression } from '@nestjs/schedule'
|
||||
|
||||
import { CLUSTER, SECURITY } from '~/app.config'
|
||||
import { CronOnce } from '~/common/decorator/cron-once.decorator'
|
||||
import { RedisKeys } from '~/constants/cache.constant'
|
||||
import { getRedisKey, md5 } from '~/utils'
|
||||
|
||||
@@ -13,8 +16,10 @@ import { CacheService } from '../redis/cache.service'
|
||||
@Injectable()
|
||||
export class JWTService {
|
||||
private secret = ''
|
||||
private readonly logger: Logger
|
||||
constructor(private readonly cacheService: CacheService) {
|
||||
this.init()
|
||||
this.logger = new Logger(JWTService.name)
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -101,15 +106,63 @@ export class JWTService {
|
||||
JSON.stringify({
|
||||
date: new Date().toISOString(),
|
||||
...info,
|
||||
}),
|
||||
} as StoreJWTPayload),
|
||||
)
|
||||
}
|
||||
|
||||
private readonly expiresDay = SECURITY.jwtExpire
|
||||
|
||||
sign(id: string, info?: { ip: string; ua: string }) {
|
||||
const token = sign({ id }, this.secret, {
|
||||
expiresIn: '30d',
|
||||
expiresIn: `${this.expiresDay}d`,
|
||||
})
|
||||
this.storeTokenInRedis(token, info || {})
|
||||
return token
|
||||
}
|
||||
|
||||
@CronOnce(CronExpression.EVERY_DAY_AT_1AM)
|
||||
async scanTable() {
|
||||
this.logger.log('--> 开始扫表,清除过期的 token')
|
||||
const redis = this.cacheService.getClient()
|
||||
const keys = await redis.hkeys(getRedisKey(RedisKeys.JWTStore))
|
||||
let deleteCount = 0
|
||||
await Promise.all(
|
||||
keys.map(async (key) => {
|
||||
const value = await redis.hget(getRedisKey(RedisKeys.JWTStore), key)
|
||||
if (!value) {
|
||||
return null
|
||||
}
|
||||
const parsed = JSON.safeParse(value) as StoreJWTPayload
|
||||
if (!parsed) {
|
||||
return null
|
||||
}
|
||||
|
||||
const date = dayjs(new Date(parsed.date))
|
||||
if (date.add(this.expiresDay, 'd').diff(new Date(), 'd') < 0) {
|
||||
this.logger.debug(
|
||||
`--> 删除过期的 token:${key}, 签发于 ${date.format(
|
||||
'YYYY-MM-DD H:mm:ss',
|
||||
)}`,
|
||||
)
|
||||
|
||||
return await redis
|
||||
.hdel(getRedisKey(RedisKeys.JWTStore), key)
|
||||
.then(() => {
|
||||
deleteCount += 1
|
||||
})
|
||||
}
|
||||
return null
|
||||
}),
|
||||
)
|
||||
|
||||
this.logger.log(`--> 删除了 ${deleteCount} 个过期的 token`)
|
||||
}
|
||||
}
|
||||
|
||||
interface StoreJWTPayload {
|
||||
/**
|
||||
* ISODateString
|
||||
*/
|
||||
date: string
|
||||
[k: string]: any
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user