如何用Next-Auth结合Fetch动态携带Token发送请求?
解决Next-Auth + Fetch携带Token请求的问题
一、先解决Session无法获取Token和user的问题
1. 检查Next-Auth配置文件
确保在pages/api/auth/[...nextauth].js(或App Router下的app/api/auth/[...nextauth]/route.js)中,正确通过jwt和session回调把token和用户信息同步到session对象:
// App Router版本示例 import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; const authOptions = { providers: [ CredentialsProvider({ async authorize(credentials) { // 调用后端登录接口,获取用户信息和token const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/seller/login`, { method: "POST", body: JSON.stringify(credentials), headers: { "Content-Type": "application/json" }, }); const userData = await res.json(); if (res.ok && userData) { // 必须返回包含token的对象,供后续jwt回调使用 return { id: userData.id, name: userData.name, accessToken: userData.accessToken }; } return null; }, }), ], session: { strategy: "jwt" }, // 强制用JWT策略,避免数据库依赖 callbacks: { async jwt({ token, user }) { // 用户登录时,将接口返回的token和用户信息合并到JWT if (user) { token.accessToken = user.accessToken; token.user = { id: user.id, name: user.name }; } return token; }, async session({ session, token }) { // 把JWT中的数据同步到session,让前端可以直接获取 session.accessToken = token.accessToken; session.user = token.user; return session; }, }, }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
2. 前端正确获取Session
- 客户端组件(Next.js 13+需加
'use client'指令):
'use client'; import { useSession } from "next-auth/react"; export default function SellerDashboard() { const { data: session, status } = useSession(); if (status === "loading") return <div>加载中...</div>; if (!session) return <div>请先登录</div>; // 现在可以正常获取session.accessToken和session.user console.log(session.accessToken, session.user); return <div>卖家后台主页</div>; }
- 服务器组件/API路由:用
getServerSession获取Session
import { getServerSession } from "next-auth/next"; import { authOptions } from "../api/auth/[...nextauth]/route"; export async function getServerSideProps(context) { const session = await getServerSession(context.req, context.res, authOptions); if (!session) { return { redirect: { destination: "/login" } }; } // 服务器端携带Token请求后端 const res = await fetch(`${process.env.API_URL}/seller/orders`, { headers: { Authorization: `Bearer ${session.accessToken}`, }, }); const orders = await res.json(); return { props: { orders } }; }
二、解决手动带Token返回401的问题
按以下步骤排查:
- 检查Token格式:后端通常要求请求头为
Authorization: Bearer <你的Token>,不要漏写Bearer前缀 - 验证Token有效性:用jwt.io解析Token,查看
exp字段是否过期,以及签名密钥是否和后端一致 - 检查后端CORS配置:Node.js后端必须允许携带
Authorization头,示例配置:
const cors = require('cors'); app.use(cors({ origin: process.env.FRONTEND_URL, // 比如http://localhost:3000 credentials: true, allowedHeaders: ['Content-Type', 'Authorization'] // 必须包含Authorization }));
- 核对后端Token验证逻辑:确认后端是从
Authorization头中提取Token,并且用正确的密钥解析,没有把accessToken和refreshToken搞混
三、封装带Token的Fetch工具函数
避免每次手动拼接请求头,封装一个复用函数:
// utils/fetchWithToken.js 'use client'; import { useSession } from "next-auth/react"; export async function fetchWithToken(url, options = {}) { const { data: session } = useSession(); if (!session?.accessToken) { throw new Error('未登录,无访问权限'); } const mergedHeaders = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${session.accessToken}`, ...options.headers, }; return fetch(url, { ...options, headers: mergedHeaders, }); }
内容的提问来源于stack exchange,提问作者Xyz.WebDeveloper
相关产品推荐
相关产品推荐

