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
相关产品推荐
相关产品推荐

