73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import { withAuth } from "next-auth/middleware"
|
|
import { NextResponse } from "next/server"
|
|
import { getMenuPermission } from "@/constants/menu"
|
|
import { evaluatePermissionExpression } from "@/constants/permissions"
|
|
|
|
export default withAuth(
|
|
// `withAuth` 会自动检查 JWT token
|
|
function middleware(req) {
|
|
const token = req.nextauth.token
|
|
const pathname = req.nextUrl.pathname
|
|
|
|
// 如果用户已登录且访问登录页面,重定向到首页
|
|
if (pathname === "/login" && token) {
|
|
return NextResponse.redirect(new URL("/", req.url))
|
|
}
|
|
|
|
// 如果访问 403 页面,直接放行
|
|
if (pathname === "/error/403") {
|
|
return NextResponse.next()
|
|
}
|
|
|
|
// 检查路由权限
|
|
if (token) {
|
|
const requiredPermission = getMenuPermission(pathname)
|
|
|
|
// 如果找到了权限要求
|
|
if (requiredPermission !== undefined) {
|
|
const userPermissions = (token.permissions as string[]) || []
|
|
const isSuperAdmin = token.isSuperAdmin as boolean
|
|
|
|
// 超级管理员拥有所有权限
|
|
if (isSuperAdmin) {
|
|
return NextResponse.next()
|
|
}
|
|
|
|
// 检查用户是否有所需权限
|
|
if (!evaluatePermissionExpression(requiredPermission, userPermissions)) {
|
|
return NextResponse.redirect(new URL("/error/403", req.url))
|
|
}
|
|
}
|
|
}
|
|
|
|
return NextResponse.next()
|
|
},
|
|
{
|
|
callbacks: {
|
|
authorized: ({ token, req }) => {
|
|
// 如果访问登录页面
|
|
if (req.nextUrl.pathname === "/login") {
|
|
return true
|
|
}
|
|
|
|
// 其他路由需要有效的 token
|
|
return !!token
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
// 配置需要保护的路由
|
|
export const config = {
|
|
matcher: [
|
|
/*
|
|
* 匹配所有路径除了:
|
|
* - /api/auth/* (NextAuth.js 路由)
|
|
* - /_next/static (static files)
|
|
* - /_next/image (image optimization files)
|
|
* - /favicon.ico (favicon file)
|
|
* - /public/* (public files)
|
|
*/
|
|
"/((?!api/auth|_next/static|_next/image|favicon.ico|public).*)",
|
|
],
|
|
} |