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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:34:57