Next.js服务器操作能否处理所有客户端交互?Cookie认证如何实现?
统一Next.js前后端请求的认证方案(DRF + Simple JWT)
针对你遇到的服务器组件/客户端组件请求认证逻辑重复的问题,有几个更简洁的统一方案,不用维护两套请求代码:
方案1:封装环境无关的请求工具函数
写一个通用的请求工具,自动判断当前运行环境(服务器/客户端)并获取token,实现一套代码适配两种场景。
步骤1:封装token获取函数
创建utils/getAuthToken.js:
import { headers } from 'next/headers'; import Cookies from 'js-cookie'; export const getAuthToken = () => { // 服务器端:从请求头的cookie中提取token if (typeof window === 'undefined') { const cookieStr = headers().get('cookie'); if (!cookieStr) return null; // 匹配你的Simple JWT token字段(假设存在access_token) const tokenMatch = cookieStr.match(/access_token=([^;]+)/); return tokenMatch ? tokenMatch[1] : null; } // 客户端:用js-cookie读取token return Cookies.get('access_token'); };
步骤2:统一请求工具
创建utils/apiRequest.js:
import { getAuthToken } from './getAuthToken'; export const apiRequest = async (url, options = {}) => { const token = getAuthToken(); const requestHeaders = { 'Content-Type': 'application/json', ...options.headers, // 携带认证头(如果有token) ...(token && { Authorization: `Bearer ${token}` }), }; const response = await fetch(`${process.env.NEXT_PUBLIC_DJANGO_API_URL}${url}`, { ...options, headers: requestHeaders, }); // 统一错误处理(比如token过期、权限不足等) if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(errorData?.detail || `请求失败: ${response.status}`); } return response.json(); };
现在不管是服务器组件还是客户端组件,直接调用apiRequest即可,无需区分环境:
// 服务器组件中获取群组 const groups = await apiRequest('/groups/'); // 客户端组件中提交表单 const handleSubmit = async () => { await apiRequest('/groups/', { method: 'POST', body: JSON.stringify({ name: '新群组' }) }); };
方案2:用Next.js API路由做请求代理
把所有前端请求先转发到Next.js的API路由,再由API路由统一处理认证并转发到Django后端。这样前端只需要请求自己的API,不用关心认证逻辑。
创建代理路由(App Router示例)
创建app/api/proxy/[...path]/route.js:
import { headers } from 'next/headers'; import { NextResponse } from 'next/server'; // 处理GET请求 export async function GET(request, { params }) { const targetUrl = `${process.env.DJANGO_API_URL}/${params.path.join('/')}`; const cookie = headers().get('cookie'); const djangoResponse = await fetch(targetUrl, { headers: { // 传递cookie给Django,让它自行解析token ...(cookie && { Cookie: cookie }), }, }); const data = await djangoResponse.json(); return NextResponse.json(data, { status: djangoResponse.status }); } // 同理实现POST/PUT/DELETE等方法 export async function POST(request, { params }) { const targetUrl = `${process.env.DJANGO_API_URL}/${params.path.join('/')}`; const cookie = headers().get('cookie'); const body = await request.json(); const djangoResponse = await fetch(targetUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(cookie && { Cookie: cookie }), }, body: JSON.stringify(body), }); const data = await djangoResponse.json(); return NextResponse.json(data, { status: djangoResponse.status }); }
前端请求时直接调用这个代理路由:
// 服务器/客户端组件通用 const groups = await fetch('/api/proxy/groups').then(res => res.json());
这种方式的好处是:认证逻辑完全集中在Next.js的API层,前端代码无需处理token;还能在代理层添加额外逻辑(比如token自动刷新、请求日志、数据格式转换)。
方案3:用Server Actions统一客户端交互(App Router专属)
如果用Next.js App Router,可以把所有需要认证的客户端操作(比如点击按钮提交表单)都通过Server Actions实现,让服务器端处理所有请求,彻底统一环境。
编写Server Action
创建actions/groupActions.js:
'use server'; import { headers } from 'next/headers'; export async function createGroup(formData) { const cookie = headers().get('cookie'); const response = await fetch(`${process.env.DJANGO_API_URL}/groups/`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(cookie && { Cookie: cookie }), }, body: JSON.stringify({ name: formData.get('name'), // 其他字段 }), }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || '创建群组失败'); } return response.json(); }
客户端组件调用Action
'use client'; import { createGroup } from '@/actions/groupActions'; export default function CreateGroupForm() { const handleSubmit = async (e) => { e.preventDefault(); const formData = new FormData(e.target); try { await createGroup(formData); // 成功后的逻辑(比如刷新列表) } catch (err) { alert(err.message); } }; return ( <form onSubmit={handleSubmit}> <input type="text" name="name" placeholder="群组名称" required /> <button type="submit">创建群组</button> </form> ); }
这种方式下,客户端组件完全不用处理token,所有请求都通过服务器端发起,和服务器组件的请求逻辑完全一致,彻底消除环境差异。
内容的提问来源于stack exchange,提问作者Kilan Van Loo
相关产品推荐
相关产品推荐

