Arj*_*jun 7 laravel next.js csrf-token laravel-sanctum next-auth
我有一个安装了 Next-Auth 的 NextJS 前端和一个使用 Sanctum 的 Laravel 后端当我尝试使用 Next-Auth 的登录功能登录时,它给了我这个错误:
Request failed with status code 419
Run Code Online (Sandbox Code Playgroud)
419 与 CSRF 令牌有关,但我在调用登录方法之前通过调用 sainttum/csrf-cookie 路由来设置令牌
[...nextauth.js]
Request failed with status code 419
Run Code Online (Sandbox Code Playgroud)
apiClient.js
CredentialsProvider
({
name: 'Email and Password',
credentials: {
email: {label: "Email", type: "email", placeholder: "Your Email"},
password: {label: "Password", type: "Password"}
},
async authorize({email, password}, req) {
await apiClient.get("/sanctum/csrf-cookie");
const user = await apiClient.post('/customer/login', {
email: email,
password: password,
});
if (user) {
return user
} else {
return null
}
}
})
Run Code Online (Sandbox Code Playgroud)
第一次尝试登录时,我被重定向到/api/auth/signIn?csrf=true
,当我再次尝试登录时,我被重定向到/api/auth/error?error=Request failed with status code 419
我尝试使用客户端的 API 调用来访问后端登录路由,并且运行顺利。
为什么两个服务器之间的请求失败,而从客户端调用时却工作正常?我不完全理解为什么 Next 服务器无法将带有 csrf 标头的请求发送到 Laravel 服务器。当涉及到服务器时,第一次调用 sainttum/csrf-cookie 时是否未设置 cookie?当两个服务器之间通信时,CSRF 不适用吗?
我在这里缺少什么?任何帮助,将不胜感激。
在评论之后,我尝试显式传递以下问题后的 cookie - Why are cookies not sent to the server via getServerSideProps in Next.js? 但我仍然收到 CSRF 令牌不匹配错误。
Jor*_*Roa 12
几天后,我找到了一个对我有用的解决方案。
首先,我们需要了解 [...nextauth.js] 的代码是服务器端的,因此它是在 Node.js 中运行的,而不是在浏览器中运行的,因此我们需要在所有请求中手动设置 cookie将在服务器端执行。
如果您的 JavaScript HTTP 库没有为您设置该值,您将需要手动设置 X-XSRF-TOKEN 标头以匹配此路由设置的 XSRF-TOKEN cookie 的值
所以我们需要手动将cookie添加到请求中。这是代码:
[...nextauth.js]
import NextAuth from "next-auth"
import Credentials from 'next-auth/providers/credentials'
import axios from "../../../lib/axios";
//This is for getting the laravel-session cookie and the CSRF cookie
//from any response of Sanctum or API Breeze
//In my case, the cookies returned are always two and I only need this,
//so you can edit for get independent of position and cookies.
const getCookiesFromResponse = (res) => {
let cookies = res.headers['set-cookie'][0].split(';')[0] + '; '
cookies += res.headers['set-cookie'][1].split(';')[0] + '; '
return cookies
}
//This is to get the X-XSRF-TOKEN from any response of Sanctum or API Breeze,
//In my case, the token is always returned first,
//so you can edit for get independent of position
const getXXsrfToken = (res) => {
return decodeURIComponent(res.headers['set-cookie'][0].split(';')[0].replace('XSRF-TOKEN=',''))
}
//This method works to make any request to your Laravel API
//res_cookies are the cookies of the response of last request you do
//obviously res_cookies is null in your first request that is "/sanctum/csrf-cookie"
const makeRequest = async (method='get', url, dataForm = null, res_cookies ) => {
const cookies = res_cookies != null ? getCookiesFromResponse(res_cookies) : null
const res = await axios.request({
method: method,
url: url,
data: dataForm,
headers: {
origin: process.env.NEXTAUTH_URL_INTERNAL, // this is your front-end URL, for example in local -> http://localhost:3000
Cookie: cookies, // set cookie manually on server
"X-XSRF-TOKEN": res_cookies ? getXXsrfToken(res_cookies) : null
},
withCredentials: true,
credentials: true,
})
return res
}
const nextAuthOptions = (req, res) => {
return {
providers: [
Credentials({
name: 'Email and Password',
credentials: {
email: { label: "Email", type: "email", placeholder: "Your Email" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
const csrf = await makeRequest('get', '/sanctum/csrf-cookie', null, null)
const user = await makeRequest('post', '/customer/login', credentials, csrf )
if(user) return user
return null
}
})
]
}
}
Run Code Online (Sandbox Code Playgroud)
lib/axios.js
import Axios from 'axios'
const axios = Axios.create({
baseURL: process.env.NEXT_PUBLIC_BACKEND_URL,
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
withCredentials: true,
credentials: true
})
export default axios
Run Code Online (Sandbox Code Playgroud)
现在如果您需要将cookie发送到前端(浏览器),您可以看到这个答案
小智 -3
我遇到了这个问题,并在花了几个小时后通过替换这一行解决了它:
import axios from 'axios';
Run Code Online (Sandbox Code Playgroud)
通过这一行:
import axios from '@/lib/axios'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7703 次 |
最近记录: |