NextJS+Redux+Django API中HttpOnly Cookie存JWT的高效方案问询
高效解决方案
1. 编写通用NextJS代理API路由
不用为每个业务接口单独编写NextJS路由,只需要创建一个统一的/api/proxy路由作为转发层,所有前端Redux请求都通过它对接Django后端:
- 前端Redux发起请求时,将目标Django接口路径、请求方法、数据一并传给这个代理路由
- 代理路由自动从HttpOnly Cookie中读取JWT令牌,添加到请求头后转发给Django后端
- 最后将Django的响应原封不动返回给前端
代码示例:
// pages/api/proxy.js import axios from 'axios'; export default async function handler(req, res) { const { target, method, data } = req.body; const token = req.cookies.jwt_token; // 假设你的JWT Cookie名为jwt_token try { const djangoResponse = await axios({ url: `${process.env.DJANGO_API_BASE}${target}`, method, data, headers: { ...(token && { Authorization: `Bearer ${token}` }), 'Content-Type': 'application/json', }, }); res.status(djangoResponse.status).json(djangoResponse.data); } catch (err) { const status = err.response?.status || 500; res.status(status).json(err.response?.data || { msg: '请求出错' }); } }
Redux调用示例:
// redux/actions/userActions.js export const getUserInfo = () => async (dispatch) => { try { const res = await fetch('/api/proxy', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ target: '/api/users/me/', method: 'GET', }), }); const data = await res.json(); dispatch({ type: 'GET_USER_SUCCESS', payload: data }); } catch (err) { dispatch({ type: 'GET_USER_FAIL', payload: err.message }); } };
2. 用NextJS Middleware统一管控页面级认证
如果需要拦截未登录用户访问特定页面,直接用Middleware统一处理,不用在每个页面写重复的认证逻辑:
- 在项目根目录创建
middleware.js,匹配所有需要保护的路由前缀 - 检查请求中的HttpOnly Cookie,无有效令牌则重定向到登录页
代码示例:
// middleware.js import { NextResponse } from 'next/server'; export function middleware(request) { const token = request.cookies.get('jwt_token'); // 定义需要保护的路由前缀 const protectedPaths = ['/dashboard', '/profile', '/settings']; const isProtected = protectedPaths.some(path => request.nextUrl.pathname.startsWith(path)); if (isProtected && !token) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); } // 配置需要匹配的路由规则 export const config = { matcher: ['/dashboard/:path*', '/profile/:path*', '/settings/:path*'], };
3. 用Redux Toolkit封装通用API切片
如果使用Redux Toolkit,可以创建一个基础API切片,所有业务接口都基于它扩展,自动复用认证逻辑:
- 用
createApi创建基础切片,将baseQuery指向代理路由 - 业务接口通过
injectEndpoints扩展,无需重复编写请求模板
代码示例:
// redux/api/baseApi.js import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; export const baseApi = createApi({ reducerPath: 'baseApi', baseQuery: fetchBaseQuery({ baseUrl: '/api/proxy' }), endpoints: () => ({}), }); // 注入用户相关业务接口 export const userApi = baseApi.injectEndpoints({ endpoints: (builder) => ({ getUserInfo: builder.query({ query: () => ({ method: 'POST', body: { target: '/api/users/me/', method: 'GET' }, }), }), }), }); // 生成Hook直接在组件中使用 export const { useGetUserInfoQuery } = userApi;
核心优势
- 通用代理路由一次性解决所有API请求的令牌携带问题,避免编写数百个重复的NextJS路由
- Middleware统一管控页面级访问权限,与API认证逻辑形成互补
- Redux Toolkit的API切片进一步简化状态管理代码,减少重复劳动
内容的提问来源于stack exchange,提问作者fortyseven
相关产品推荐
相关产品推荐

