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

React结合PHP后端如何传递CSRF令牌保护POST请求

如何在React前端向PHP后端传递CSRF令牌保护POST请求

一、PHP后端生成并暴露CSRF令牌

  • 先启动PHP会话,生成唯一CSRF令牌并存入会话,同时通过两种方式暴露给前端:
    session_start();
    // 生成32位随机CSRF令牌(会话中不存在时创建)
    if (!isset($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    
    // 方式1:嵌入到页面meta标签(适合React嵌入PHP服务端渲染页面的场景)
    echo '<meta name="csrf-token" content="' . $_SESSION['csrf_token'] . '">';
    
    // 方式2:通过独立接口返回(适合前后端分离的纯React项目)
    // 示例接口:/api/get-csrf-token
    header('Content-Type: application/json');
    echo json_encode(['csrf_token' => $_SESSION['csrf_token']]);
    

二、React前端获取并携带令牌

场景1:React嵌入PHP服务端渲染页面

  • 直接从页面meta标签读取令牌,在POST请求头中携带:
    // 提取meta标签中的CSRF令牌
    const getCsrfToken = () => {
      const metaTag = document.querySelector('meta[name="csrf-token"]');
      return metaTag ? metaTag.getAttribute('content') : '';
    };
    
    // 登录接口请求示例
    const handleLogin = async (username, password) => {
      const csrfToken = getCsrfToken();
      try {
        const res = await fetch('/api/login', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': csrfToken // 令牌放在自定义请求头
          },
          body: JSON.stringify({ username, password })
        });
        const data = await res.json();
        // 处理登录结果
      } catch (err) {
        // 处理请求错误
      }
    };
    

场景2:前后端分离的纯React项目

  • 先通过GET请求获取令牌,存储后在POST请求中携带:
    import { useEffect, useState } from 'react';
    
    const ChatComponent = () => {
      const [csrfToken, setCsrfToken] = useState('');
    
      // 页面加载时获取CSRF令牌
      useEffect(() => {
        const fetchToken = async () => {
          const res = await fetch('/api/get-csrf-token');
          const data = await res.json();
          setCsrfToken(data.csrf_token);
        };
        fetchToken();
      }, []);
    
      // 发送聊天消息请求示例
      const sendMessage = async (content) => {
        if (!csrfToken) return;
        try {
          const res = await fetch('/api/send-chat', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'X-CSRF-Token': csrfToken
            },
            body: JSON.stringify({ content })
          });
          const data = await res.json();
          // 更新聊天列表
        } catch (err) {
          // 处理发送错误
        }
      };
    
      return <div>{/* 聊天界面 */}</div>;
    };
    

三、PHP后端验证令牌有效性

  • 在所有需要保护的POST接口中,校验请求头中的令牌与会话存储的令牌是否一致:
    session_start();
    // 从请求头获取前端传递的令牌
    $receivedToken = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
    // 验证令牌合法性
    if (!$receivedToken || $receivedToken !== $_SESSION['csrf_token']) {
        http_response_code(403);
        echo json_encode(['error' => '无效的CSRF令牌']);
        exit;
    }
    // 验证通过,执行接口业务逻辑
    

注意事项

  • 确保每个用户会话对应唯一的CSRF令牌,避免跨用户复用
  • 令牌除了放在请求头,也可以放在请求体中,只要前后端约定一致即可
  • 表单提交场景下,也可以将令牌作为隐藏表单字段,React提交时携带该字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 08:50:23