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

在Next.js中实现Google Auth时如何安全配置允许登录用户列表?

安全实现NextAuth用户权限验证的方案

1. 迁移用户列表到后端,避免客户端暴露

不要在客户端代码中导入allowed-users.json,将该文件放置在后端专属目录(比如data/allowed-users.json,确保不在public或其他客户端可直接访问的路径下)。

2. 借助NextAuth回调完成后端验证

在pages/api/auth/[...nextauth].js中配置jwt和session回调,在服务器端完成用户邮箱验证,并为session添加权限标识:

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import allowedUsers from "../../../data/allowed-users.json"; // 后端路径

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  callbacks: {
    async jwt({ token, user }) {
      // 用户首次登录时验证邮箱并分配权限
      if (user) {
        const isAllowed = allowedUsers.includes(user.email);
        // 可扩展为多权限体系,比如区分管理员/员工/客户
        token.role = isAllowed ? "employee" : "customer";
        token.isAllowed = isAllowed;
      }
      return token;
    },
    async session({ session, token }) {
      // 将后端验证后的权限信息同步到前端session
      session.user.role = token.role;
      session.user.isAllowed = token.isAllowed;
      return session;
    },
  },
});

3. 改造Login组件,基于后端返回的权限判断

无需在客户端导入用户列表,直接使用session中后端传递的权限字段:

import React from "react";
import { useSession, signIn, signOut } from "next-auth/react";
import GoogleButton from "react-google-button";
import { useRouter } from "next/router";

const Login = () => {
  const { data: session, status } = useSession();
  const router = useRouter();

  // 处理登录状态加载中场景
  if (status === "loading") {
    return <div>加载中...</div>;
  }

  if (!session) {
    return (
      <div className="flex justify-center items-center content-center h-full">
        <GoogleButton onClick={() => signIn()} />
      </div>
    );
  }

  if (session.user.isAllowed) {
    router.push("/account");
  } else {
    signOut();
  }

  return null; // 避免渲染多余内容
};

export default Login;

4. 页面级权限保护(可选)

为防止未授权用户直接通过URL访问/account等受保护页面,可选择以下两种方式:

方式1:使用getServerSideProps

在pages/account.js中添加服务端校验:

import { getSession } from "next-auth/react";

export async function getServerSideProps(context) {
  const session = await getSession(context);
  if (!session || !session.user.isAllowed) {
    return {
      redirect: {
        destination: "/login",
        permanent: false,
      },
    };
  }
  return { props: {} };
}

方式2:使用Next.js Middleware

创建middleware.js全局拦截请求:

import { getToken } from "next-auth/jwt";
import { NextResponse } from "next/server";

export async function middleware(req) {
  const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
  const { pathname } = req.nextUrl;

  // 拦截/account路径的未授权访问
  if (pathname.startsWith("/account")) {
    if (!token || !token.isAllowed) {
      return NextResponse.redirect(new URL("/login", req.url));
    }
  }

  return NextResponse.next();
}

5. 拓展多权限体系

如果需要区分管理员、员工、客户,可将用户列表改为键值对格式:

{
  "admin@example.com": "admin",
  "employee@example.com": "employee",
  "customer@example.com": "customer"
}

然后在jwt回调中调整逻辑:

const role = allowedUsers[user.email] || "customer";
token.role = role;
token.isAllowed = role !== "customer"; // 根据业务需求调整权限判断规则

规范做法总结

  • 敏感数据绝不放客户端:用户列表、权限配置属于敏感信息,必须存放在后端或数据库中。
  • 后端执行验证逻辑:利用NextAuth的jwt和session回调在服务器端完成用户权限校验,确保逻辑不可被客户端篡改。
  • 添加多层权限防护:除了登录页的判断,还要对受保护页面做访问拦截,避免未授权访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 07:25:27