如何在NEXTJS中获取Laravel CSRF值



我有一个Next JS前端和Laravel 9作为后端。创建了API并在邮递员上进行了测试。所有API运行良好,没有任何问题。

问题

因此,我创建了一个带有表单的Nextjs文件,并使用Axios发布数据。我得到了Error: Request failed with status code 419

已尝试

StackOverflow上有多个类似问题的答案。我照着答案做了,但没有任何问题。

  1. 更改VerifyCsrfToken.php代码以禁用csrf保护。(i想要保留csrf(

  2. 尝试使用Axios中的headers选项添加csrf cookie。(Axios POST到Laravel API导致419个错误(

  3. 使用(PHP手工密钥:generate(生成密钥

  4. 添加了会话域

  5. 在web中间件中添加了路由

Route::group(['middleware' => ['api']], function () {
// our routes
});

什么在起作用

  1. 允许VerifyCsrfToken.php中的所有域正常工作

我想获得csrf代币

`const csrf=((=>axios.get('/sancum/csrf-cookie'('

我得到csrf令牌/csrf-cookie的空值。并且没有发现对该请求的已接受应答失败,状态代码为419。

有人知道我做错了什么吗?

尝试将中间件从web更改为api

Route::group(['middleware' => ['api']], function () {
// our routes
});

如果您的前端没有csrf令牌,并且希望禁用对该特定路由的检查,则需要将该路由添加到App\Http\Middleware\VerifyCsrfToken.php中的$except数组中class:

<?php namespace AppHttpMiddleware;
use IlluminateFoundationHttpMiddlewareVerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
'your route here',
];
}

我不知道Nextjs,但基本上你可以把Laravel CSRF令牌放在HTML文档的元标签上,比如这个

<meta name="csrf-token" content="{{ csrf_token() }}" />

然后你可以使用像这样的简单javascript来访问它

var csrf = document.querySelector('meta[name="csrf-token"]').content;

根据laravel:的文档

在Laravel中进行这3项更改

  1. 更新cors策略(config/cors.php(

来源:'supports_credentials' => false,

收件人:'supports_credentials' => true,

  1. 在(resources/js/bootstrap.js(中添加行

axios.defaults.withCredentials = true;

  1. 在laravel的.env文件中添加后端和前端url
APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:3000

现在在NEXT JS应用程序中执行以下操作

  1. 在根目录下添加.env.local文件并添加以下代码。NEXT_PUBLIC_BACKEND_URL=http://localhost:8000'

  2. 使用npm i axios安装axios

  3. 在使用AXIOS发布数据之前,使用AXIOS导入CSRF令牌,然后使用AXIOS张贴表单数据。

这是发送或获取数据的示例代码

import React, { useEffect, useState } from 'react';
import axios from 'axios';
//optional toastify library
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
export default function index({data}) {
//console.log(data); 
//setting the state (getting form data into veriable)
const [title, setTitle] = useState('')
const [desc, setDesc] = useState('')

// preventing default and showing the data in console
const formSubmit = async (e) => {
e.preventDefault();
console.log(title ,desc);
// setting csrf token
await axios.get('http://localhost:8000/sanctum/csrf-cookie').then(getcsrvf => {

//console.log(getcsrvf);

// posting the data using axios / creating the data.
axios.post('http://localhost:8000/api/post', {title,desc})
.then(function (response) {
//alert(response.data.message);

toast(response.data.message);

console.log(response);
})
.catch(function (error) {
//console.log(error);
});
});
} 

return (
// bootstrap installed
<div className=' pt-5'>
<div className='container'>
//basic jsx form
<form onSubmit={formSubmit}> 
<div className='mb-2'> 
{/* onChange={(e)=>{setName(e.target.value)}} */}
<input type="text" onChange={(e) => {setTitle(e.target.value)}} value={title} className="form-control mb-2 py-2" placeholder="title" name="title" id='title' />
</div>  
<div className='mb-2'>
<input type="text" onChange={(e) => {setDesc(e.target.value)}} value={desc} className="form-control mb-2 py-2" placeholder="desc" name="desc" id='desc' />
</div>  

<div className='mb-2'>
<button className='btn btn-primary'>Submit</button>
</div>  
</form> 
</div>

<hr/>
//looping the post data
{data.post.map((post, i)=>{
return (
<div className='container' key={i}>
<h3>{post.title}</h3>
<p>{post.desc}</p>
<hr/>
</div>
)
})}

<ToastContainer position="top-center" pauseOnHover="false"/>
</div>
)
}
// Getting the records // reading the data
export async function getServerSideProps() {

const res = await fetch("http://localhost:8000/api/post")
const data = await res.json()
return{
props: {
data
}
}
}

注意:请将http://localhost:8000更改为您的laravle url,将http://localhost:3000更改为您前端url。

上述解决方案对我有效。

最新更新