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

不使用Redux,如何将accessToken传入Axios拦截器?

问题描述

我正在尝试使用手动JWT策略,通过现有Node.js后端对Next.js应用进行授权。后端会颁发access token,我希望通过axios.interceptor为每个请求添加Bearer ${token}签名,相关代码如下:

// utils/axios.ts

const axiosPrivate = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
  timeout: 1000,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
  },
});

axiosPrivate.interceptors.request.use(
  (config: AxiosRequestConfig): AxiosRequestConfig => {
    if (config.headers === undefined) {
      config.headers = {};
    }

    // 无法访问 sessionStorage 或 document.cookies

    config.headers['Authorization'] = `Bearer ${accessToken}`

    return config;
  }
);

export { axiosPrivate }

我的问题是:有没有不使用Redux就能获取access token的方法?
我希望在拦截器中实现这一点,这样就能像下面这样进行SSR:

// pages/dashboard.tsx

export const getServerSideProps: GetServerSideProps = async (context) => {

  const res = await axiosPrivate.get('/dashboard'); // 请求已自动签名

  return {
    props: {
      dashboard: res.data,
    },
  };
};

解决方案

Next.js存在客户端浏览器和服务端SSR两种运行环境,需要针对不同场景分别处理token获取,不用Redux的话可以试试下面几种方案:

1. 给拦截器加外部传参逻辑(兼顾SSR和客户端)

修改axios拦截器,允许从请求配置里传入token,同时兼容客户端环境从本地存储获取:

// utils/axios.ts
import axios, { AxiosRequestConfig } from 'axios';

const axiosPrivate = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
  timeout: 1000,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
  },
});

axiosPrivate.interceptors.request.use(
  // 扩展配置类型,支持传入token
  (config: AxiosRequestConfig & { token?: string }): AxiosRequestConfig => {
    if (!config.headers) config.headers = {};

    // 优先用请求时传入的token,客户端环境下再尝试从localStorage取
    const token = config.token || (typeof window !== 'undefined' ? window.localStorage.getItem('accessToken') : null);
    
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }

    return config;
  }
);

export { axiosPrivate }

在SSR的getServerSideProps里,从请求上下文的cookie中拿token并传入:

// pages/dashboard.tsx
import { axiosPrivate } from '../utils/axios';

export const getServerSideProps: GetServerSideProps = async (context) => {
  // 从服务端请求的cookie中提取token(推荐把accessToken存在HttpOnly cookie里)
  const accessToken = context.req.cookies.accessToken;

  const res = await axiosPrivate.get('/dashboard', {
    token: accessToken
  });

  return {
    props: {
      dashboard: res.data,
    },
  };
};

2. 封装可传入token的axios实例(更灵活)

直接封装一个创建axios实例的函数,每次使用时传入对应环境的token:

// utils/axios.ts
import axios, { AxiosRequestConfig } from 'axios';

export const createAxiosPrivate = (token?: string) => {
  const instance = axios.create({
    baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
    timeout: 1000,
    withCredentials: true,
    headers: {
      'Content-Type': 'application/json',
      // 初始化时直接带上token
      ...(token && { Authorization: `Bearer ${token}` })
    },
  });

  // 可选:添加响应拦截器处理token过期等逻辑
  instance.interceptors.response.use(
    res => res,
    async err => {
      // 这里可以加token刷新逻辑
      return Promise.reject(err);
    }
  );

  return instance;
};

SSR场景使用:

// pages/dashboard.tsx
import { createAxiosPrivate } from '../utils/axios';

export const getServerSideProps: GetServerSideProps = async (context) => {
  const accessToken = context.req.cookies.accessToken;
  const axiosPrivate = createAxiosPrivate(accessToken);
  
  const res = await axiosPrivate.get('/dashboard');

  return {
    props: {
      dashboard: res.data,
    },
  };
};

客户端组件使用:

// components/ClientComponent.tsx
'use client';
import { createAxiosPrivate } from '../utils/axios';

const ClientComponent = () => {
  const fetchData = async () => {
    const token = localStorage.getItem('accessToken');
    const axiosPrivate = createAxiosPrivate(token);
    const res = await axiosPrivate.get('/user/profile');
    // 处理返回数据
  };

  return <button onClick={fetchData}>获取用户信息</button>;
};

关键注意事项

  • 优先把access token存在HttpOnly cookie中,能避免XSS攻击,这种情况下客户端无法通过document.cookie访问,SSR必须从服务端上下文的req.cookies获取。
  • 区分服务端和客户端环境的核心是判断typeof window !== 'undefined',服务端环境不存在window对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:05:34