From 9647b7d3c981ec96e4993875e503480116aa61b1 Mon Sep 17 00:00:00 2001 From: feie9456 Date: Sat, 28 Jun 2025 17:38:57 +0800 Subject: [PATCH] fix basic auth --- app/api/version/route.ts | 0 lib/middleware.ts | 3 +- middleware.ts | 70 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 app/api/version/route.ts create mode 100644 middleware.ts diff --git a/app/api/version/route.ts b/app/api/version/route.ts new file mode 100644 index 0000000..e69de29 diff --git a/lib/middleware.ts b/lib/middleware.ts index ed84c55..adbee17 100644 --- a/lib/middleware.ts +++ b/lib/middleware.ts @@ -5,7 +5,7 @@ export function withAuth(handler: (req: NextRequest) => Promise) { return async (req: NextRequest) => { const url = new URL(req.url) - // Skip auth for certain paths + // Skip auth for certain paths (same logic as original Express app) if ( url.pathname.startsWith('/api/') || url.pathname.startsWith('/screenshots/') || @@ -17,6 +17,7 @@ export function withAuth(handler: (req: NextRequest) => Promise) { return handler(req) } + // For all other paths, require authentication const authHeader = req.headers.get('authorization') if (!authHeader) { diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 0000000..0fae1a3 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,70 @@ +import { NextRequest, NextResponse } from 'next/server' +import { config } from './lib/config' + +export function middleware(req: NextRequest) { + const url = new URL(req.url) + + // Skip auth for certain paths (same logic as original Express app) + if ( + url.pathname.startsWith('/api/') || + url.pathname.startsWith('/screenshots/') || + url.pathname.startsWith('/downloads/') || + url.pathname.includes('install') || + url.pathname.includes('WinupdateCore') || + req.method === 'POST' || + url.pathname.startsWith('/_next/') || // Next.js static files + url.pathname.startsWith('/favicon.ico') || // Favicon + url.pathname.startsWith('/api-test') // API test page (for development) + ) { + return NextResponse.next() + } + + // For all other paths, require authentication + const authHeader = req.headers.get('authorization') + + if (!authHeader) { + return new NextResponse('Authentication required', { + status: 401, + headers: { + 'WWW-Authenticate': 'Basic realm="Restricted Access"' + } + }) + } + + try { + const auth = Buffer.from(authHeader.split(' ')[1], 'base64').toString() + const [username, password] = auth.split(':') + + if (username === config.auth.username && password === config.auth.password) { + return NextResponse.next() + } else { + return new NextResponse('Authentication failed', { + status: 401, + headers: { + 'WWW-Authenticate': 'Basic realm="Restricted Access"' + } + }) + } + } catch { + return new NextResponse('Invalid authentication', { + status: 401, + headers: { + 'WWW-Authenticate': 'Basic realm="Restricted Access"' + } + }) + } +} + +// 配置中间件匹配的路径 +export const config_middleware = { + matcher: [ + /* + * Match all request paths except for the ones starting with: + * - api (API routes) + * - _next/static (static files) + * - _next/image (image optimization files) + * - favicon.ico (favicon file) + */ + '/((?!_next/static|_next/image|favicon.ico).*)', + ], +}