2026-05-25 14:31:58 +08:00

133 lines
3.0 KiB
TypeScript

import { cookies } from 'next/headers';
import { mainPrisma } from './db';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
// JWT 密钥 - 必须通过环境变量配置,不再提供默认值
const JWT_SECRET = (() => {
const secret = process.env.JWT_SECRET;
if (!secret) {
console.error('[SECURITY] JWT_SECRET 环境变量未设置,管理员认证功能将不可用');
} else if (secret.length < 32) {
console.error('[SECURITY] JWT_SECRET 长度不足 32 字节,建议使用更长的密钥');
}
return secret || '';
})();
const TOKEN_EXPIRY = '24h';
export interface AdminSession {
id: string;
username: string;
}
/**
* 验证管理员登录
*/
export async function verifyAdmin(
username: string,
password: string
): Promise<{ success: boolean; token?: string; error?: string }> {
try {
const admin = await mainPrisma.admin.findUnique({
where: { username },
});
if (!admin) {
return { success: false, error: '用户名或密码错误' };
}
const isValid = await bcrypt.compare(password, admin.passwordHash);
if (!isValid) {
return { success: false, error: '用户名或密码错误' };
}
const token = jwt.sign(
{ id: admin.id, username: admin.username },
JWT_SECRET,
{ expiresIn: TOKEN_EXPIRY }
);
return { success: true, token };
} catch (error) {
console.error('验证失败:', error);
return { success: false, error: '服务器错误' };
}
}
/**
* 验证 JWT token
*/
export function verifyToken(token: string): AdminSession | null {
try {
const decoded = jwt.verify(token, JWT_SECRET) as AdminSession;
return decoded;
} catch {
return null;
}
}
/**
* 从请求中获取当前管理员会话
*/
export async function getAdminSession(): Promise<AdminSession | null> {
const cookieStore = await cookies();
const token = cookieStore.get('admin_token')?.value;
if (!token) {
return null;
}
return verifyToken(token);
}
/**
* 创建管理员账号(用于初始化)
*/
export async function createAdmin(
username: string,
password: string
): Promise<{ success: boolean; error?: string }> {
try {
const existing = await mainPrisma.admin.findUnique({
where: { username },
});
if (existing) {
return { success: false, error: '用户名已存在' };
}
const passwordHash = await bcrypt.hash(password, 10);
await mainPrisma.admin.create({
data: {
username,
passwordHash,
},
});
return { success: true };
} catch (error) {
console.error('创建管理员失败:', error);
return { success: false, error: '服务器错误' };
}
}
/**
* 生成许可证密钥
*/
export function generateLicenseKey(): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const segments: string[] = [];
for (let i = 0; i < 4; i++) {
let segment = '';
for (let j = 0; j < 4; j++) {
segment += chars.charAt(Math.floor(Math.random() * chars.length));
}
segments.push(segment);
}
return segments.join('-');
}