开源前加固认证与部署契约:加密随机 JWT、改密事务吊销、登录 CSRF,并禁止生产回落 localhost。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 02:07:34 +08:00
parent 6f054a903c
commit 3b550f2124
24 changed files with 372 additions and 355 deletions

View File

@@ -2,7 +2,7 @@
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { useLayoutEffect, useRef, type KeyboardEvent, type ReactNode } from "react";
import { useRef, type KeyboardEvent, type ReactNode } from "react";
import { Globe } from "lucide-react";
import {
AdminPageHeader,
@@ -19,32 +19,11 @@ const NAV: { href: string; label: string }[] = [
{ href: "/admin/settings/maintenance", label: "维护与诊断" },
];
/** 旧 #hash / ?section= → 独立路由 */
const LEGACY: Record<string, string> = {
basic: "/admin/settings/basic",
content: "/admin/settings/access",
security: "/admin/settings/access",
access: "/admin/settings/access",
mail: "/admin/settings/mail",
storage: "/admin/settings/storage",
filter: "/admin/settings/filter",
maintenance: "/admin/settings/maintenance",
};
export default function SettingsShell({ children }: { children: ReactNode }) {
const pathname = usePathname();
const router = useRouter();
const navRefs = useRef<(HTMLAnchorElement | null)[]>([]);
useLayoutEffect(() => {
const hash = window.location.hash.replace(/^#/, "").trim();
const section = new URLSearchParams(window.location.search).get("section") || hash;
if (!section) return;
const dest = LEGACY[section];
if (!dest || dest === pathname) return;
router.replace(dest);
}, [pathname, router]);
const onNavKeyDown = (e: KeyboardEvent<HTMLAnchorElement>, i: number) => {
if (
e.key !== "ArrowDown" &&

View File

@@ -5,24 +5,7 @@ export const metadata: Metadata = {
title: "站点设置",
};
interface PageProps {
searchParams: Promise<{ section?: string }>;
}
const LEGACY: Record<string, string> = {
basic: "/admin/settings/basic",
content: "/admin/settings/access",
security: "/admin/settings/access",
access: "/admin/settings/access",
mail: "/admin/settings/mail",
storage: "/admin/settings/storage",
filter: "/admin/settings/filter",
maintenance: "/admin/settings/maintenance",
};
/** /admin/settings 与旧 ?section= 统一跳到子路由 */
export default async function SettingsIndexPage({ searchParams }: PageProps) {
const sp = await searchParams;
const raw = typeof sp.section === "string" ? sp.section.trim() : "";
redirect(LEGACY[raw] || "/admin/settings/basic");
/** /admin/settings 统一进入基本信息子路由 */
export default async function SettingsIndexPage() {
redirect("/admin/settings/basic");
}