feat: table scan to delete outdate token

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2022-07-25 23:05:35 +08:00
parent 34ef33f1a5
commit 19791bbae8
2 changed files with 57 additions and 4 deletions

View File

@@ -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,
}

View File

@@ -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
}