Add registration flow and improve admin post management

This commit is contained in:
爱喝水的木子
2026-03-19 20:17:56 +08:00
parent 50a1e476c8
commit 17f5f6adcb
28 changed files with 799 additions and 192 deletions

View File

@@ -3,6 +3,8 @@ import { NextRequest } from "next/server";
const COOKIE_NAME = "admin_session";
const encoder = new TextEncoder();
let cachedKey: CryptoKey | null = null;
let cachedSecret: string | null = null;
function getSecret() {
const secret = process.env.SESSION_SECRET;
@@ -15,16 +17,32 @@ function getSecret() {
export type SessionPayload = {
role: "admin";
iat: number;
exp?: number;
uid?: string;
name?: string;
};
async function hmacSha256(data: string, secret: string): Promise<string> {
const key = await crypto.subtle.importKey(
export function getAdminName() {
return process.env.ADMIN_NAME?.trim() || "Admin";
}
async function getHmacKey(secret: string) {
if (cachedKey && cachedSecret === secret) {
return cachedKey;
}
cachedSecret = secret;
cachedKey = await crypto.subtle.importKey(
"raw",
encoder.encode(secret),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
return cachedKey;
}
async function hmacSha256(data: string, secret: string): Promise<string> {
const key = await getHmacKey(secret);
const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(data));
return Buffer.from(sig).toString("base64url");
}
@@ -45,6 +63,12 @@ export async function verifySession(token?: string): Promise<SessionPayload | nu
if (check !== sig) return null;
try {
const payload = JSON.parse(Buffer.from(base, "base64url").toString());
if (typeof payload?.exp !== "number") {
return null;
}
if (Date.now() > payload.exp) {
return null;
}
return payload;
} catch {
return null;
@@ -57,11 +81,12 @@ export async function requireAdminFromRequest(req: NextRequest): Promise<boolean
}
export function setAdminCookie(token: string) {
const isProd = process.env.NODE_ENV === "production";
cookies().set(COOKIE_NAME, token, {
httpOnly: true,
sameSite: "lax",
secure: true,
maxAge: 60 * 60 * 24 * 30
secure: isProd,
maxAge: 60 * 60 * 24
});
}