You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next 13客户端组件中结合Lucia Auth实现isAdmin权限校验

解决Lucia Auth管理员权限校验的方案

核心问题在于getPageSession依赖服务端专属的next/headers,不能直接在客户端组件中调用。下面是几种可行的实现方式:

方案一:服务端页面前置校验(推荐)

把权限校验逻辑放在服务端页面组件中,通过后再渲染客户端的Admin组件:

// app/admin/page.tsx(服务端组件,无需加"use client")
import { redirect } from 'next/navigation';
import { getPageSession } from '@/lib/auth';
import AdminClient from './AdminClient';

export default async function AdminPage() {
  // 1. 校验登录状态
  const session = await getPageSession();
  if (!session) {
    redirect('/login');
  }

  // 2. 校验管理员权限(直接在服务端查询数据库或调用内部逻辑)
  const userRole = await getUserRole(session.user.userId);
  if (userRole !== 'admin') {
    redirect('/login'); // 也可跳转到无权限提示页
  }

  // 3. 权限通过,渲染客户端组件
  return <AdminClient />;
}

客户端组件只需专注于交互逻辑:

// app/admin/AdminClient.tsx(客户端组件)
'use client';

export default function AdminClient() {
  return (
    <div>
      <h1>管理员控制台</h1>
      {/* 你的客户端交互内容 */}
    </div>
  );
}

方案二:全局路由中间件校验

用Next.js Middleware拦截所有/admin开头的请求,提前完成权限校验:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getPageSession } from '@/lib/auth';

export async function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/admin')) {
    const session = await getPageSession();
    
    // 未登录跳转登录页
    if (!session) {
      return NextResponse.redirect(new URL('/login', request.url));
    }

    // 非管理员跳转
    const userRole = await getUserRole(session.user.userId);
    if (userRole !== 'admin') {
      return NextResponse.redirect(new URL('/login', request.url));
    }

    // 权限通过,放行请求
    return NextResponse.next();
  }
}

// 指定拦截的路由规则
export const config = {
  matcher: '/admin/:path*',
};

这种方式适合全局统一管控路由权限,无需在每个页面重复写校验逻辑。

方案三:客户端动态校验(Server Actions)

如果需要在客户端组件内动态校验权限(比如操作前校验),可以用Server Actions封装服务端逻辑:

// app/admin/AdminClient.tsx(客户端组件)
'use client';
import { useRouter } from 'next/navigation';
import { checkAdminPermission } from './actions';
import { useEffect } from 'react';

export default function AdminClient() {
  const router = useRouter();

  // 组件挂载时二次校验(可选,作为服务端校验的补充)
  useEffect(() => {
    const verifyPermission = async () => {
      const isAdmin = await checkAdminPermission();
      if (!isAdmin) router.push('/login');
    };
    verifyPermission();
  }, [router]);

  return <div>管理员控制台</div>;
}

封装Server Action:

// app/admin/actions.ts
'use server';
import { getPageSession } from '@/lib/auth';

export async function checkAdminPermission() {
  const session = await getPageSession();
  if (!session) return false;

  const userRole = await getUserRole(session.user.userId);
  return userRole === 'admin';
}

内容的提问来源于stack exchange,提问作者deadcoder0904

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:52:45