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

React Redux中跨页面复用登录JWT Token并在请求头携带的方法

React+Redux项目全局复用JWT Token并自动携带鉴权的实现流程

1. 登录成功后持久化存储Token

登录接口拿到后端返回的JWT后,需要同时存储到两个位置,保证全项目可复用且刷新不丢失:

  • Redux全局状态:所有页面、组件可以直接读取登录态、Token做权限判断
  • localStorage/sessionStorage:做持久化,避免页面刷新后Redux状态重置导致登录态失效

参考代码:

// 登录action逻辑示例
function login(loginForm) {
  return async (dispatch) => {
    try {
      const res = await axios.post('http://localhost:9091/login', loginForm)
      const token = res.data.token // 按接口实际返回的Token字段取值
      // 持久化到本地存储
      localStorage.setItem('jwt_token', token)
      // 同步到Redux全局状态
      dispatch({
        type: 'SET_LOGIN_TOKEN',
        payload: token
      })
      // 登录成功后的跳转逻辑
    } catch (err) {
      // 登录失败提示逻辑
    }
  }
}

对应的用户状态reducer配置:

// src/store/reducers/userReducer.js
const initialState = {
  // 初始化时直接从本地存储读,保证刷新后初始状态带Token
  token: localStorage.getItem('jwt_token') || '',
  // 其他用户信息字段按需添加
}
export default function userReducer(state = initialState, action) {
  switch(action.type) {
    case 'SET_LOGIN_TOKEN':
      return { ...state, token: action.payload }
    case 'CLEAR_LOGIN_STATE':
      // 退出登录、鉴权失败时清空存储
      localStorage.removeItem('jwt_token')
      return { ...state, token: '' }
    default:
      return state
  }
}

2. 封装带统一拦截器的Axios实例

不要在每个action文件中直接引入原生axios,单独抽离公共请求工具,通过请求拦截器统一给所有需要鉴权的接口加请求头,避免每个接口重复写加Token的逻辑。

新建src/utils/request.js文件:

import axios from 'axios'
import store from '../store' // 引入项目的Redux store实例

// 创建统一axios实例
const service = axios.create({
  baseURL: 'http://localhost:9091', // 接口统一前缀,后续写接口不用重复写域名
  timeout: 10000
})

// 请求拦截器:发请求前自动注入Token
service.interceptors.request.use(
  config => {
    const token = localStorage.getItem('jwt_token')
    if (token) {
      // 头字段、格式按后端约定调整,通用格式为Bearer + Token
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  error => Promise.reject(error)
)

// 响应拦截器:统一处理鉴权失败场景
service.interceptors.response.use(
  response => {
    return response.data // 直接返回接口data层,后续调用不用重复写res.data
  },
  error => {
    // 401状态码代表Token无效、过期,直接清空登录态跳登录页
    if (error.response?.status === 401) {
      store.dispatch({ type: 'CLEAR_LOGIN_STATE' })
      window.location.href = '/login'
    }
    return Promise.reject(error)
  }
)

export default service

3. 改造现有UPI接口请求

把原来upi action中引入的原生axios替换为封装好的请求实例,所有后续新增的需要鉴权的接口,都统一用这个实例发送,会自动在请求头携带Token。

改造后的upi action代码:

// 替换原来的原生axios引入
import request from '../utils/request';
export const upiAction = {
    upi,
};
function upi(user) {
    return (dispatch) => {
        var data = {
            upiId: user.upiId,
            accountNumber: user.accountNumber,
        };
        request // 替换为封装好的实例,自动携带Token
            .post('/upiidcreation', data) // 配置了baseURL后直接写接口路径即可
            .then((res) => {
                console.log("res", res);
                alert(JSON.stringify(res.responseDesc));
            })
            .catch(err => {
                dispatch(setUserUpiError(err, true));
                alert("Please Check With details");
            });
    };
}

export function setUserUpi(showError) {
    return {
        type: 'SET_UPI_SUCCESS',
       showError: showError,
    };
}

export function setUserUpiError(error, showError) {
    return {
        type: 'SET_UPI_ERROR',
        error: error,
        showError: showError,
    };
}

注意事项

  • 请求头的Token格式要和后端约定一致,如果后端要求自定义头字段(比如X-Token)、不需要Bearer前缀,直接修改请求拦截器里的headers配置即可。
  • 对安全性要求高的场景,可以把Token存在sessionStorage,关闭浏览器自动清除,比localStorage风险更低。
  • 退出登录时记得手动调用CLEAR_LOGIN_STATE的action,清空本地存储和Redux里的Token。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:15:27