Revert "feat: use middleware to auth"

This reverts commit f57cdb5ec1.
This commit is contained in:
shinya
2025-06-30 23:17:05 +08:00
parent afef6d9865
commit 240764e81b
5 changed files with 53 additions and 92 deletions

View File

@@ -24,41 +24,6 @@ export async function POST(req: NextRequest) {
);
}
// 登录成功:写入 HttpOnly Cookie
const res = NextResponse.json({ ok: true });
res.cookies.set({
name: 'password',
value: password,
httpOnly: true,
sameSite: 'lax',
secure: process.env.NODE_ENV === 'production',
maxAge: 60 * 60 * 24 * 30, // 30 天
path: '/',
});
return res;
} catch (error) {
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
}
}
// 使用 Cookie 校验登录状态
export async function GET(req: NextRequest) {
try {
const result = process.env.PASSWORD;
// 未设置 PASSWORD 则直接放行
if (!result) {
return NextResponse.json({ ok: true });
}
const cookiePassword = req.cookies.get('password')?.value;
const matched = cookiePassword === result;
if (!matched) {
return NextResponse.json({ ok: false }, { status: 401 });
}
return NextResponse.json({ ok: true });
} catch (error) {
return NextResponse.json({ error: '服务器错误' }, { status: 500 });

View File

@@ -3,6 +3,7 @@ import { Inter } from 'next/font/google';
import './globals.css';
import AuthProvider from '../components/AuthProvider';
import { ThemeProvider } from '../components/ThemeProvider';
const inter = Inter({ subsets: ['latin'] });
@@ -37,7 +38,7 @@ export default function RootLayout({
enableSystem
disableTransitionOnChange
>
{children}
<AuthProvider>{children}</AuthProvider>
</ThemeProvider>
</body>
</html>

View File

@@ -27,6 +27,11 @@ function LoginPageClient() {
});
if (res.ok) {
// 保存密码以供后续请求使用
if (typeof window !== 'undefined') {
localStorage.setItem('password', password);
}
const redirect = searchParams.get('redirect') || '/';
router.replace(redirect);
} else if (res.status === 401) {

View File

@@ -0,0 +1,46 @@
'use client';
import { usePathname, useRouter } from 'next/navigation';
import { useEffect } from 'react';
interface Props {
children: React.ReactNode;
}
export default function AuthProvider({ children }: Props) {
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
// 登录页或 API 路径不做校验,避免死循环
if (pathname.startsWith('/login')) return;
const password = localStorage.getItem('password');
const fullPath =
typeof window !== 'undefined'
? window.location.pathname + window.location.search
: pathname;
// 有密码时验证
(async () => {
try {
const res = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password }),
});
if (!res.ok) {
// 校验未通过,清理并跳转登录
localStorage.removeItem('password');
router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`);
}
} catch (error) {
// 网络错误等也认为未登录
router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`);
}
})();
}, [pathname, router]);
return <>{children}</>;
}

View File

@@ -1,56 +0,0 @@
import { NextRequest, NextResponse } from 'next/server';
// 全站(含 /api鉴权中间件运行于 Edge Runtime。
export async function middleware(req: NextRequest) {
const { pathname, search } = req.nextUrl;
// 1. 放行无需鉴权的路径
if (
pathname.startsWith('/login') || // 登录页
pathname.startsWith('/api/login') || // 登录接口
pathname.startsWith('/_next') || // Next.js 静态文件
pathname === '/favicon.ico' ||
pathname.startsWith('/icons') ||
pathname === '/manifest.json' ||
pathname === '/logo.png' ||
pathname === '/screenshot.png'
) {
return NextResponse.next();
}
// 内部请求标记,避免递归拦截
if (req.headers.get('x-internal-auth') === 'true') {
return NextResponse.next();
}
// 通过后端接口验证登录状态GET /api/login
const origin = req.nextUrl.origin;
const verifyRes = await fetch(`${origin}/api/login`, {
method: 'GET',
headers: {
Cookie: req.headers.get('cookie') || '',
'x-internal-auth': 'true',
},
});
if (verifyRes.ok) {
return NextResponse.next();
}
// 未通过校验API 返回 401页面跳转登录
if (pathname.startsWith('/api')) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const loginUrl = req.nextUrl.clone();
loginUrl.pathname = '/login';
loginUrl.searchParams.set('redirect', pathname + search);
return NextResponse.redirect(loginUrl);
}
// 2. 指定哪些路径使用 middleware
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico|manifest.json|icons|logo.png|screenshot.png|api/login).*)',
],
};