66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import { type NextRequest, NextResponse } from "next/server";
|
||
import { getToken } from "next-auth/jwt";
|
||
|
||
export async function middleware(request: NextRequest) {
|
||
const { pathname } = request.nextUrl;
|
||
|
||
// 允许访问 ping 端点
|
||
if (pathname.startsWith("/ping")) {
|
||
return NextResponse.next();
|
||
}
|
||
|
||
// 允许访问认证相关 API
|
||
if (pathname.startsWith("/api/auth")) {
|
||
return NextResponse.next();
|
||
}
|
||
|
||
// 允许访问钉钉回调页面(public 文件夹中的文件)
|
||
if (pathname === "/dingtalk-callback.html") {
|
||
return NextResponse.next();
|
||
}
|
||
|
||
// 检测是否为 HTTPS(通过 AUTH_URL 或请求协议判断)
|
||
const isSecure = process.env.AUTH_URL?.startsWith("https://") ||
|
||
request.nextUrl.protocol === "https:";
|
||
|
||
const token = await getToken({
|
||
req: request,
|
||
secret: process.env.AUTH_SECRET,
|
||
secureCookie: isSecure,
|
||
});
|
||
|
||
const externalBase =
|
||
process.env.AUTH_URL ??
|
||
`${request.nextUrl.protocol}//${request.headers.get("host") ?? request.nextUrl.host}`;
|
||
|
||
// 未登录用户只能访问 /login 和 /register
|
||
if (!token && !["/login", "/register"].includes(pathname)) {
|
||
const loginUrl = new URL("/login", externalBase);
|
||
// 保存当前路径作为回调 URL
|
||
loginUrl.searchParams.set("callbackUrl", pathname);
|
||
return NextResponse.redirect(loginUrl);
|
||
}
|
||
|
||
// 已登录用户访问 /login 或 /register 时重定向到首页
|
||
if (token && ["/login", "/register"].includes(pathname)) {
|
||
return NextResponse.redirect(new URL("/", externalBase));
|
||
}
|
||
|
||
return NextResponse.next();
|
||
}
|
||
|
||
export const config = {
|
||
matcher: [
|
||
/*
|
||
* 匹配所有请求路径,除了:
|
||
* - api/auth (NextAuth.js)
|
||
* - _next/static (静态文件)
|
||
* - _next/image (图片优化文件)
|
||
* - favicon.ico (favicon文件)
|
||
* - public 文件夹中的文件
|
||
*/
|
||
"/((?!api/auth|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
|
||
],
|
||
};
|
||
|