优化后端鉴权与日志安全

This commit is contained in:
yml2213
2026-05-26 08:21:11 +08:00
parent 851d1d1efc
commit dea3023825
35 changed files with 402 additions and 185 deletions
@@ -23,6 +23,7 @@ export type AdminSession = {
username: string
role: AdminRole
expiresAt: string
sessionVersion: number
}
type AdminRole = 'admin' | 'operator' | 'support'
@@ -137,12 +138,22 @@ export async function verifyAdminSessionToken(token: unknown): Promise<AdminSess
})
}
const tokenSessionVersion = Number(payload?.ver || 0)
const currentSessionVersion = normalizeAdminSessionVersion(user.session_version)
if (tokenSessionVersion !== currentSessionVersion) {
throw createHttpError('后台登录态已失效,请重新登录', {
statusCode: 401,
errorCode: 'admin_auth_stale',
})
}
return {
sessionId: String(payload?.sid || '').trim(),
userId: Number(user.id),
username: String(user.username || ''),
role: normalizeAdminRole(user.role),
expiresAt,
sessionVersion: currentSessionVersion,
}
}
@@ -248,6 +259,7 @@ export async function updateManagedAdminUserRole(
await ensureAdminUserChangeAllowed(user, { nextRole: role }, session)
const updated = await updateAdminUser(user.id, {
role,
session_version: nextAdminSessionVersion(user),
updated_at: nowIso(),
})
@@ -273,6 +285,7 @@ export async function updateManagedAdminUserStatus(
await ensureAdminUserChangeAllowed(user, { nextStatus: status }, session)
const updated = await updateAdminUser(user.id, {
status,
session_version: nextAdminSessionVersion(user),
updated_at: nowIso(),
})
@@ -295,6 +308,7 @@ export async function resetManagedAdminUserPassword(userId: number | string, pay
validatePassword(password)
const updated = await updateAdminUser(user.id, {
password_hash: hashAdminPassword(password),
session_version: nextAdminSessionVersion(user),
updated_at: nowIso(),
})
@@ -325,6 +339,7 @@ function createAdminSession(user: AdminUserRow): JsonObject {
uid: Number(user.id),
usr: String(user.username || ''),
role: normalizeAdminRole(user.role),
ver: normalizeAdminSessionVersion(user.session_version),
iat: issuedAt,
exp: expiresAt,
}
@@ -430,6 +445,15 @@ function validatePassword(password: string): void {
}
}
function normalizeAdminSessionVersion(value: unknown): number {
const parsed = Number(value)
return Number.isInteger(parsed) && parsed > 0 ? parsed : 1
}
function nextAdminSessionVersion(user: AdminUserRow): number {
return normalizeAdminSessionVersion(user.session_version) + 1
}
async function getRequiredAdminUser(userId: number | string): Promise<AdminUserRow> {
const user = await getAdminUserById(Number(userId))