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

Next.js 14组件中获取Session信息的正确实现方法咨询

适配Next.js 14 + Next Auth v5 Beta的Session获取方案

核心问题原因

你用的getServerSideProps是Pages Router专属API,在App Router环境下完全不支持,直接传递session会导致组件props类型不匹配,这就是报错的根源。以下是适配你当前技术栈的几种正确实现方式:


1. 先确认Next Auth v5的基础配置

确保你的auth.ts配置符合v5 Beta的规范,结合Prisma Adapter的示例如下:

// app/auth.ts
import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "./lib/prisma";
import bcrypt from "bcryptjs"; // 假设用bcrypt做密码验证

export const { auth, signIn, signOut, handlers } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    Credentials({
      credentials: {
        email: { label: "邮箱", type: "email" },
        password: { label: "密码", type: "password" },
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) return null;
        
        const user = await prisma.user.findUnique({
          where: { email: credentials.email },
        });
        
        if (!user || !user.password) return null;
        
        const passwordMatch = await bcrypt.compare(credentials.password, user.password);
        return passwordMatch ? user : null;
      },
    }),
  ],
  session: { strategy: "jwt" }, // 或选"database",根据需求决定
  secret: process.env.NEXTAUTH_SECRET,
});

// 扩展Session类型,适配你的用户模型
declare module "next-auth" {
  interface Session {
    user: {
      id: string;
      email: string;
      // 按需添加name、avatar等自定义字段
    } & DefaultSession["user"];
  }
}

2. React Server Components(RSC)中获取Session

App Router下的组件默认是RSC,可直接在组件内部调用auth()获取session(无需传props):

// app/account/settings/page.tsx
import { auth } from "@/app/auth";
import { redirect } from "next/navigation";

export default async function AccountSettings() {
  // 直接在服务器端获取session
  const session = await auth();

  // 未登录时重定向到登录页
  if (!session) redirect("/login");

  return (
    <div className="container">
      <h1>账户设置</h1>
      <div className="user-info">
        <p>当前登录邮箱:{session.user.email}</p>
        <p>用户ID:{session.user.id}</p>
      </div>
      {/* 这里添加设置表单,比如修改密码、个人信息等 */}
    </div>
  );
}

3. Client Components中获取Session

如果你的组件需要客户端交互(比如用useState、表单提交),需先标记为Client Component,再用useSession钩子:

第一步:在根Layout中配置SessionProvider

// app/layout.tsx
import { SessionProvider } from "next-auth/react";
import { auth } from "./auth";
import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "我的应用",
  description: "基于Next.js 14的项目",
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  // 从服务器端获取初始session,传给Provider
  const session = await auth();

  return (
    <html lang="zh-CN">
      <body>
        <SessionProvider session={session}>
          {children}
        </SessionProvider>
      </body>
    </html>
  );
}

第二步:编写Client Component版本的AccountSettings

// app/account/settings/ClientSettings.tsx
"use client";

import { useSession } from "next-auth/react";
import { useState } from "react";

export default function ClientSettings() {
  const { data: session, status } = useSession();
  const [newPassword, setNewPassword] = useState("");

  if (status === "loading") return <div>加载中...</div>;
  if (!session) return <div>请先登录</div>;

  const handlePasswordChange = async (e: React.FormEvent) => {
    e.preventDefault();
    // 这里调用Server Action修改密码
  };

  return (
    <div className="container">
      <h1>账户设置(客户端交互版)</h1>
      <p>当前用户:{session.user.email}</p>
      <form onSubmit={handlePasswordChange}>
        <input
          type="password"
          value={newPassword}
          onChange={(e) => setNewPassword(e.target.value)}
          placeholder="输入新密码"
          required
        />
        <button type="submit">修改密码</button>
      </form>
    </div>
  );
}

4. Server Actions中获取Session

在Server Actions里直接调用auth()即可拿到session,用于授权验证:

// app/actions/accountActions.ts
"use server";

import { auth } from "@/app/auth";
import prisma from "@/app/lib/prisma";
import bcrypt from "bcryptjs";

export async function updateUserPassword(newPassword: string) {
  const session = await auth();

  // 未授权时抛出错误
  if (!session?.user.id) throw new Error("请先登录");

  const hashedPassword = await bcrypt.hash(newPassword, 10);
  
  await prisma.user.update({
    where: { id: session.user.id },
    data: { password: hashedPassword },
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:33:17