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

如何在React Redux Saga应用中实现CSRF防护?

嘿,在React Redux Saga项目里实现CSRF防护其实挺直观的,核心是和后端配合好,同时在Saga处理请求的环节把必要的Token带上。我给你拆解几个关键步骤,一步步来:

第一步:先让后端配置好CSRF Token的生成与传递

CSRF防护的前提是后端能生成并传递Token给前端,常见的做法有两种:

  • Cookie存储:后端在用户首次访问时,把Token放在一个非HttpOnly的Cookie里(比如XSRF-TOKEN),这样前端能读取到。同时要设置好Cookie的SameSite属性(推荐Strict或Lax),防止跨站滥用。
  • 响应头传递:后端在API响应的头里返回Token(比如X-CSRF-Token),前端可以从响应头中提取。
第二步:前端写个工具函数获取CSRF Token

不管后端用哪种方式传递,你都需要一个函数来拿到Token。比如针对Cookie的情况:

// 从Cookie中提取XSRF Token的工具函数
const getCsrfToken = () => {
  const cookieMatch = document.cookie.match(/XSRF-TOKEN=([^;]+)/);
  return cookieMatch ? cookieMatch[1] : null;
};

如果是从响应头拿,就可以在首次请求后把Token存在全局状态(比如Redux store)里,后续直接从store取。

第三步:在Redux Saga的请求中带上Token

接下来就是在Saga发起请求时,把Token放到请求头里。这里分两种常用的请求库来举例:

用原生Fetch的情况

import { call, put } from 'redux-saga/effects';

function* submitFormSaga(action) {
  try {
    const csrfToken = getCsrfToken();
    // 发起POST请求,在headers里带上Token
    const response = yield call(fetch, '/api/submit-form', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-XSRF-TOKEN': csrfToken // 这里的头名要和后端约定好,比如有的后端用X-CSRF-Token
      },
      body: JSON.stringify(action.payload)
    });

    if (!response.ok) throw new Error('请求失败');
    const result = yield call([response, 'json']);
    yield put({ type: 'SUBMIT_FORM_SUCCESS', payload: result });
  } catch (error) {
    yield put({ type: 'SUBMIT_FORM_FAILURE', error: error.message });
  }
}

用Axios的情况

更省心的方式是给Axios设置请求拦截器,全局自动带上Token:

import axios from 'axios';
import { call, put } from 'redux-saga/effects';

// 创建Axios实例
const apiClient = axios.create({
  baseURL: '/api',
});

// 添加请求拦截器,自动注入CSRF Token
apiClient.interceptors.request.use((config) => {
  const csrfToken = getCsrfToken();
  if (csrfToken) {
    config.headers['X-XSRF-TOKEN'] = csrfToken;
  }
  return config;
});

// 在Saga里使用这个实例
function* fetchUserSaga() {
  try {
    const response = yield call(apiClient.get, '/user/profile');
    yield put({ type: 'FETCH_USER_SUCCESS', payload: response.data });
  } catch (error) {
    yield put({ type: 'FETCH_USER_FAILURE', error: error.message });
  }
}
第四步:处理Token无效或过期的情况

如果后端返回403状态码(说明CSRF验证失败),你可以在Saga里捕获这个错误,做相应的处理:

function* submitFormSaga(action) {
  try {
    // ... 正常请求逻辑
  } catch (error) {
    if (error.response?.status === 403) {
      // 可以尝试重新获取Token(比如调用后端的刷新Token接口)
      yield call(refreshCsrfToken);
      // 然后重试当前请求
      yield put(action);
    } else {
      yield put({ type: 'SUBMIT_FORM_FAILURE', error: error.message });
    }
  }
}

// 示例:重新获取CSRF Token的Saga
function* refreshCsrfToken() {
  yield call(fetch, '/api/refresh-csrf-token', { method: 'GET' });
}
几个关键注意事项
  • 不要把Token存在localStorage:XSS攻击可以轻松窃取localStorage里的内容,而存在非HttpOnly的Cookie里,配合SameSite属性,安全性更高。
  • 后端必须验证Token:前端带Token只是一半,后端要对比请求头里的Token和Cookie里的Token是否一致,这才是防护的核心。
  • 跨域场景要额外配置:如果你的前端和后端是跨域的,要确保后端允许携带Cookie(设置Access-Control-Allow-Credentials: true),同时前端请求要加上credentials: 'include'(Fetch)或withCredentials: true(Axios)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:01:33