React与Laravel集成:迁移Blade登录表单至React时的CSRF令牌认证问题
解决React调用Laravel API时的CSRF认证问题
嘿,我帮你梳理下在React前端对接Laravel API时,如何替代Blade里的@csrf实现CSRF认证,这些都是实际项目里验证过的方案:
核心原理回顾
Laravel的CSRF保护默认支持两种验证方式:
- 表单提交时携带
_token字段(就是Blade里@csrf生成的隐藏输入框) - 发送请求时携带
X-XSRF-TOKEN请求头,对应后端设置的XSRF-TOKENCookie
因为React是SPA,我们更推荐用请求头的方式来处理,下面是具体实现步骤:
方案1:手动获取CSRF Token并携带请求头
步骤1:读取XSRF-TOKEN Cookie
Laravel会自动在响应中设置XSRF-TOKEN Cookie,你可以用原生JS或者js-cookie库来读取它:
- 原生JS读取Cookie的方法:
function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); } const csrfToken = getCookie('XSRF-TOKEN');
- 用
js-cookie库(更简洁):
先安装依赖:
npm install js-cookie
然后读取:
import Cookies from 'js-cookie'; const csrfToken = Cookies.get('XSRF-TOKEN');
步骤2:在登录请求中携带请求头
以axios为例(React项目常用的HTTP库),发送登录请求时添加X-XSRF-TOKEN头:
import axios from 'axios'; import Cookies from 'js-cookie'; const LoginForm = () => { const handleSubmit = async (e) => { e.preventDefault(); const email = e.target.email.value; const password = e.target.password.value; try { const csrfToken = Cookies.get('XSRF-TOKEN'); const response = await axios.post('/api/login', { email, password }, { headers: { 'X-XSRF-TOKEN': csrfToken }, withCredentials: true // 允许携带Cookie,这很重要 }); // 处理登录成功逻辑,比如跳转到首页 console.log('登录成功:', response.data); } catch (error) { // 处理登录失败,比如显示错误提示 console.error('登录失败:', error.response.data); } }; return ( <form onSubmit={handleSubmit} id="login-form"> {/* 你的表单元素:邮箱、密码、记住我等 */} <div className="form-group"> <label>E-mail*</label> <input type="text" name="email" placeholder="Email" /> </div> <div className="form-group"> <label>Senha*</label> <input type="password" name="password" placeholder="Senha" /> </div> <button type="submit" className="btn btn-primary">Login</button> </form> ); }; export default LoginForm;
方案2:全局配置axios自动携带CSRF头
如果你的项目有很多API请求,不想每个请求都手动加头,可以配置axios的全局拦截器,自动读取Cookie并添加请求头:
// 在src/utils/axios.js(或类似的配置文件)中 import axios from 'axios'; import Cookies from 'js-cookie'; // 允许携带Cookie axios.defaults.withCredentials = true; // 请求拦截器:自动添加CSRF头 axios.interceptors.request.use(config => { const csrfToken = Cookies.get('XSRF-TOKEN'); if (csrfToken) { config.headers['X-XSRF-TOKEN'] = csrfToken; } return config; }); export default axios;
之后在组件里直接导入这个配置好的axios即可,不用再手动处理CSRF头:
import axios from '../utils/axios'; // 登录请求直接写 const response = await axios.post('/api/login', { email, password });
方案3:配合Laravel Sanctum(推荐SPA场景)
如果你的项目是完全分离的SPA,推荐用Laravel Sanctum来处理CSRF和认证:
- 先确保后端安装并配置好Sanctum
- 在React中先请求
/sanctum/csrf-cookie接口,这个接口会自动设置CSRF Cookie,然后再发送登录请求:
const handleLogin = async (email, password) => { try { // 先获取CSRF Cookie await axios.get('/sanctum/csrf-cookie'); // 再发送登录请求 const response = await axios.post('/api/login', { email, password }); // 处理成功逻辑 } catch (error) { // 处理错误 } };
关键配置注意事项
- CORS配置:在Laravel的
config/cors.php中确保以下配置正确:
return [ 'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['http://localhost:3000'], // 替换成你的React应用域名 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true, // 必须设为true,允许携带Cookie ];
- 开发环境跨域:如果React和Laravel在不同端口运行(比如React在3000,Laravel在8000),要确保React的请求地址是Laravel的完整域名(比如
http://localhost:8000/api/login),而不是相对路径。
内容的提问来源于stack exchange,提问作者Gabriel Andrade Vianna
相关产品推荐
相关产品推荐

