114 lines
2.9 KiB
TypeScript
114 lines
2.9 KiB
TypeScript
"use server"
|
|
|
|
import redis from "./redis"
|
|
import { deleteCachedSession, getOrLoadSession } from "./session-cache"
|
|
import {
|
|
getClientIpFromRequest,
|
|
getSessionRedisKeyFromCookieValue,
|
|
SESSION_COOKIE_NAME,
|
|
} from "./session-common"
|
|
|
|
const roundDurationMs = (durationMs: number) =>
|
|
Math.round(durationMs * 100) / 100
|
|
|
|
// 校验用户信息
|
|
export async function genAccessToken(req: any) {
|
|
const sessionLookupStart = performance.now()
|
|
let redisLookupMs = 0
|
|
let sessionSource: "memory" | "shared" | "redis" | "skip" = "skip"
|
|
|
|
try {
|
|
const sessionData = req?.cookies?.get?.(SESSION_COOKIE_NAME)?.value
|
|
const redisKey = getSessionRedisKeyFromCookieValue(sessionData)
|
|
|
|
// 无session 直接重定向到登录页面
|
|
if (!redisKey) {
|
|
return {
|
|
ok: false as const,
|
|
message: "客户端请求中,未包含用户标识",
|
|
timing: {
|
|
sessionLookupMs: roundDurationMs(
|
|
performance.now() - sessionLookupStart
|
|
),
|
|
redisLookupMs: 0,
|
|
sessionSource,
|
|
},
|
|
}
|
|
}
|
|
|
|
const sessionResult = await getOrLoadSession(redisKey, async () => {
|
|
const redisLookupStart = performance.now()
|
|
const userDataString = await redis.get(redisKey)
|
|
redisLookupMs = roundDurationMs(performance.now() - redisLookupStart)
|
|
|
|
if (!userDataString) {
|
|
return null
|
|
}
|
|
|
|
return JSON.parse(userDataString)
|
|
})
|
|
|
|
sessionSource = sessionResult.source
|
|
|
|
// redis中无用户信息 直接重定向到登录页面
|
|
if (!sessionResult.data) {
|
|
deleteCachedSession(redisKey)
|
|
return {
|
|
ok: false as const,
|
|
message: "未获取到用户信息",
|
|
timing: {
|
|
sessionLookupMs: roundDurationMs(
|
|
performance.now() - sessionLookupStart
|
|
),
|
|
redisLookupMs,
|
|
sessionSource,
|
|
},
|
|
}
|
|
}
|
|
|
|
const userData = sessionResult.data
|
|
const clientIP = getClientIpFromRequest(req)
|
|
|
|
if (clientIP !== userData?.clientIP) {
|
|
return {
|
|
ok: false as const,
|
|
message: `客户端信息与缓存用户信息不一致 \n 客户端: ${clientIP} | redis存储: ${userData?.clientIP}`,
|
|
timing: {
|
|
sessionLookupMs: roundDurationMs(
|
|
performance.now() - sessionLookupStart
|
|
),
|
|
redisLookupMs,
|
|
sessionSource,
|
|
},
|
|
}
|
|
}
|
|
|
|
return {
|
|
ok: true as const,
|
|
userData: {
|
|
...userData,
|
|
redisKey,
|
|
},
|
|
timing: {
|
|
sessionLookupMs: roundDurationMs(
|
|
performance.now() - sessionLookupStart
|
|
),
|
|
redisLookupMs,
|
|
sessionSource,
|
|
},
|
|
}
|
|
} catch (err: any) {
|
|
return {
|
|
ok: false as const,
|
|
message: `获取用户信息报错, 报错原因:${err?.message}`,
|
|
timing: {
|
|
sessionLookupMs: roundDurationMs(
|
|
performance.now() - sessionLookupStart
|
|
),
|
|
redisLookupMs,
|
|
sessionSource,
|
|
},
|
|
}
|
|
}
|
|
}
|