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

基于Node.js API(JWT)的Next.js多认证与路由角色权限处理咨询

Next.js 多认证、路由与角色权限控制方案(基于JWT后端)

认证方案选型

结合你的技术栈(Next.js + Node.js JWT),推荐两种主流方案,按需选择:

1. 自定义JWT认证流程

适合需要完全控制认证逻辑、无第三方依赖的场景:

  • JWT存储:优先使用HttpOnly Cookie存储JWT(比localStorage更安全,避免XSS攻击),后端登录接口返回Set-Cookie头
  • JWT验证:在Next.js的Middleware(全局)或getServerSideProps(页面级)中验证JWT有效性
  • 路由保护:通过Middleware拦截需要认证的路由,未登录或权限不足时重定向

2. NextAuth.js 集成

适合快速搭建认证体系,支持多认证提供商(邮箱密码、OAuth等),同时兼容自定义JWT后端:

  • 用Credentials Provider对接你的Node.js登录接口,获取JWT和用户角色
  • 配置JWT会话策略,在回调中注入角色信息
  • 内置的useSession钩子和Middleware可快速实现路由保护

核心实现细节

1. 角色权限设计

在Node.js后端生成JWT时,将角色信息(如role: 'admin'/'user'/'editor')加入payload,示例:

// Node.js 后端登录接口
const jwt = require('jsonwebtoken');
app.post('/login', (req, res) => {
  // 验证用户账号密码逻辑...
  const user = { id: 1, email: 'user@example.com', role: 'admin' };
  const token = jwt.sign(user, process.env.JWT_SECRET, { expiresIn: '1d' });
  // 设置HttpOnly Cookie
  res.cookie('auth_token', token, { 
    httpOnly: true, 
    secure: process.env.NODE_ENV === 'production', 
    maxAge: 86400000 
  });
  res.json({ success: true });
});

2. 全局路由保护(Middleware)

Next.js 13+ 推荐用Middleware实现全局路由拦截,示例:

// middleware.js
import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';

export function middleware(request) {
  const token = request.cookies.get('auth_token')?.value;
  const { pathname } = request.nextUrl;

  // 公开路由无需验证
  if (['/login', '/register', '/'].includes(pathname)) {
    return NextResponse.next();
  }

  // 未登录重定向到登录页
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // 验证JWT并检查角色
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    // 管理员路由仅允许admin角色访问
    if (pathname.startsWith('/admin') && decoded.role !== 'admin') {
      return NextResponse.redirect(new URL('/forbidden', request.url));
    }
    // 普通用户路由允许user/editor/admin访问
    if (pathname.startsWith('/dashboard') && !['user', 'editor', 'admin'].includes(decoded.role)) {
      return NextResponse.redirect(new URL('/forbidden', request.url));
    }
  } catch (err) {
    // JWT无效或过期,重定向登录
    return NextResponse.redirect(new URL('/login', request.url));
  }

  return NextResponse.next();
}

// 指定需要拦截的路由
export const config = {
  matcher: ['/dashboard/:path*', '/admin/:path*', '/profile'],
};

3. 页面级权限控制(Pages Router)

如果用Pages Router,可在getServerSideProps中验证权限:

// pages/admin/dashboard.js
import jwt from 'jsonwebtoken';

export async function getServerSideProps(context) {
  const token = context.req.cookies.auth_token;

  if (!token) {
    return { redirect: { destination: '/login', permanent: false } };
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    if (decoded.role !== 'admin') {
      return { redirect: { destination: '/forbidden', permanent: false } };
    }
    return { props: { user: decoded } };
  } catch (err) {
    return { redirect: { destination: '/login', permanent: false } };
  }
}

export default function AdminDashboard({ user }) {
  return <div>Welcome Admin: {user.email}</div>;
}

4. NextAuth.js 集成示例

// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';

export default NextAuth({
  session: { strategy: 'jwt' },
  providers: [
    CredentialsProvider({
      credentials: {
        email: { label: 'Email', type: 'text' },
        password: { label: 'Password', type: 'password' }
      },
      async authorize(credentials) {
        // 调用Node.js后端登录接口
        const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/login`, {
          method: 'POST',
          body: JSON.stringify(credentials),
          headers: { 'Content-Type': 'application/json' }
        });
        const data = await res.json();
        if (res.ok && data.user) {
          return { ...data.user, token: data.token };
        }
        return null;
      }
    })
  ],
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.role = user.role;
        token.accessToken = user.token;
      }
      return token;
    },
    async session({ session, token }) {
      session.user.role = token.role;
      session.accessToken = token.accessToken;
      return session;
    }
  }
});

用useSession保护组件:

// components/EditorPanel.js
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import { useEffect } from 'react';

export default function EditorPanel() {
  const { data: session, status } = useSession();
  const router = useRouter();

  useEffect(() => {
    if (status === 'authenticated' && session.user.role !== 'editor' && session.user.role !== 'admin') {
      router.push('/forbidden');
    }
  }, [session, status, router]);

  if (status === 'loading') return <div>Loading...</div>;
  if (!session) return <div>Please login to access this page</div>;

  return <div>Editor Panel Content</div>;
}

方案对比

方案优势劣势
自定义JWT认证完全可控,无第三方依赖,灵活性高需手动处理JWT验证、会话管理等细节
NextAuth.js 集成快速搭建,内置多认证方式,减少重复代码依赖第三方库,自定义逻辑受框架限制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:45:31