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

寻求Next.js v13.4 AppRouter下Laravel Breeze API与NextAuth.js集成方案

Laravel Breeze API + Next.js 13.4+ App Router + NextAuth.js 集成指南

环境准备

  • Laravel 10+ 并完成 Breeze API 安装
  • Next.js 13.4+(启用 App Router)
  • Node.js 18+

Laravel Breeze API 配置

  1. 安装 Breeze API:
    composer require laravel/breeze --dev
    php artisan breeze:install api
    
  2. 配置 CORS:修改config/cors.php
    • paths添加/api/*
    • allowed_origins设为你的 Next.js 域名(如http://localhost:3000)
    • supports_credentials设为true
  3. 配置 Sanctum:
    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
    
    修改config/sanctum.php的stateful数组,加入你的 Next.js 域名
  4. 测试登录接口:发送POST /api/login请求,确认返回包含token和user的响应

Next.js 端配置

1. 安装依赖

npm install next-auth axios

2. 创建 NextAuth 配置文件

新建app/api/auth/[...nextauth]/route.ts:

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import axios from "axios";

export const authOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) return null;

        try {
          const res = await axios.post(
            `${process.env.NEXT_PUBLIC_LARAVEL_API_URL}/api/login`,
            { email: credentials.email, password: credentials.password },
            { withCredentials: true }
          );

          return res.data.user ? { ...res.data.user, token: res.data.token } : null;
        } catch (err) {
          console.error(err);
          return null;
        }
      },
    }),
  ],
  session: { strategy: "jwt" },
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.user = user;
        token.accessToken = user.token;
      }
      return token;
    },
    async session({ session, token }) {
      session.user = token.user as any;
      session.accessToken = token.accessToken as string;
      return session;
    },
  },
  pages: { signIn: "/login" },
};

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

3. 配置环境变量

在.env.local中添加:

NEXT_PUBLIC_LARAVEL_API_URL=http://localhost:8000
NEXTAUTH_SECRET=your-nextauth-secret-here # 用命令生成:openssl rand -hex 32
NEXTAUTH_URL=http://localhost:3000

4. App Router 中使用 Auth

客户端组件:登录页面(app/login/page.tsx)

"use client";

import { useState } from "react";
import { signIn } from "next-auth/react";
import { useRouter } from "next/navigation";

export default function LoginPage() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const router = useRouter();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const result = await signIn("credentials", { email, password, redirect: false });
    
    result?.ok ? router.push("/dashboard") : alert("登录失败,请检查账号密码");
  };

  return (
    <div className="max-w-md mx-auto mt-10">
      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <label>邮箱</label>
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            className="w-full p-2 border rounded"
            required
          />
        </div>
        <div>
          <label>密码</label>
          <input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            className="w-full p-2 border rounded"
            required
          />
        </div>
        <button type="submit" className="w-full p-2 bg-blue-500 text-white rounded">
          登录
        </button>
      </form>
    </div>
  );
}

服务端组件:受保护的仪表盘(app/dashboard/page.tsx)

import { getServerSession } from "next-auth/next";
import { authOptions } from "../api/auth/[...nextauth]/route";
import axios from "axios";
import { redirect } from "next/navigation";

export default async function DashboardPage() {
  const session = await getServerSession(authOptions);
  if (!session) redirect("/login");

  // 服务端请求 Laravel API 获取用户数据
  const userRes = await axios.get(
    `${process.env.NEXT_PUBLIC_LARAVEL_API_URL}/api/user`,
    {
      headers: { Authorization: `Bearer ${session.accessToken}` },
      withCredentials: true,
    }
  );

  return (
    <div className="max-w-md mx-auto mt-10">
      <h1 className="text-xl font-bold">仪表盘</h1>
      <p className="mt-4">欢迎回来,{userRes.data.name}!</p>
    </div>
  );
}

客户端组件:用户信息展示(app/components/UserInfo.tsx)

"use client";

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

export default function UserInfo() {
  const { data: session } = useSession();
  return session ? <p>当前用户:{session.user.email}</p> : <p>未登录</p>;
}

登出功能(客户端组件)

"use client";

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

export function LogoutButton() {
  return (
    <button
      onClick={() => signOut({ redirect: true, callbackUrl: "/login" })}
      className="text-blue-500 ml-4"
    >
      登出
    </button>
  );
}

测试验证

  1. 启动 Laravel 服务:php artisan serve
  2. 启动 Next.js 服务:npm run dev
  3. 访问http://localhost:3000/login,用 Laravel 后台创建的用户登录,验证跳转逻辑
  4. 进入仪表盘,确认能正常获取用户数据
  5. 点击登出,验证是否回到登录页

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:57:46