我使用 Django-REST Framework 开发了一个 API,并尝试将其与我的前端连接。
我有一个端点来获得最后四名获胜者,当我尝试时它工作正常
async function getLastFourWinners() {
const url = 'http://127.0.0.1:8000/bets/get_last_four_winners'
const response = await fetch(url)
if (!response.ok) {
throw new Error('Failed to fetch data')
}
return response.json()
}
export default async function Home() {
const winners = await getLastFourWinners()
return (
<main>
{winners.map((winner, index) => (
<LastWinnerItem
key={index}
username={winner.username}
roundName={winner.round}
leagueName={winner.league}
nPoints={winner.points}
nPlayers={winner.n_players}
pool={winner.pool}
imagePath={winner.profile_image}
/>
))}
</main>
)
}
但是,当我从 /login 登录,然后尝试从我的家获取当前登录的用户时,我收到一条错误消息,指出我未经身份验证。但是当我使用 Postman 执行相同操作时,它会正确返回用户。
这是我的/登录名:
'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
import './login.css'
export default function Login() {
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const router = useRouter()
const url = 'http://127.0.0.1:8000/user/login/'
const handleLogin = async(e) => {
e.preventDefault();
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({username, password}),
credentials: 'include',
})
console.log(response)
if (response.ok) {
// router.push('/')
console.log('ok')
} else {
console.error('Login failed')
}
} catch(error) {
console.error('Error during login')
}
}
return (
<main className='container__main py-4'>
<div className="card o-hidden border-0 shadow-lg w-75 mx-auto my-4">
<div className="card-header py-3 login__header">
<h4 className="m-0 font-weight-bold">Log in</h4>
</div>
<div className="card-body">
<form onSubmit={handleLogin}>
<input
type="text"
id="username"
name="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="form-control mb-4"
placeholder="Username..."
required
/>
<input
type="password"
id="password"
name="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="form-control mb-4"
placeholder="Password..."
required
/>
<small>Do not have a user? <a href="/signup" className='signup__btn'>Sign up</a></small>
<div className="login__button d-flex justify-content-center">
<button type="submit" className="btn text-center px-5 py-2 align-items-center">LOG IN</button>
</div>
</form>
</div>
</div>
</main>
)
}
这就是我在主页上尝试做的事情
async function getUser() {
const response = await fetch('http://127.0.0.1:8000/user/user', {
method: 'GET',
credentials: 'include'
})
if(!response.ok) {
throw new Error('Failed to fetch data')
} else {
return response.json()
}
}
export default async function Home() {
const user = await getUser()
return (
<main>
<p>{user.username}</p>
</main>
)
}
当我向 /user/login 发出 post 请求时,正确创建了 sessionid,当我在浏览器中访问 127.0.0.1:8000/user/user 时,我得到了登录的用户,这就是为什么我相信问题出在getUser(),但我无法解决它
请告诉我我是否清楚或者是否需要更多信息来帮助我。先谢谢你了
问题可能是 Django 后端未正确配置 CORS 策略,以允许使用来自 Next.js 前端的凭据进行跨域请求。
有几件事需要检查:
在 Django 设置中,确保安装并配置了 CORS 中间件,以允许使用凭据的 Next.js 源/域:
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = [
"http://localhost:3000"
]
CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
]
在您看来,服务于/user/user,设置标头以允许凭据并公开响应标头:
response = JsonResponse({'username': user.username})
response["Access-Control-Allow-Credentials"] = "true"
response["Access-Control-Expose-Headers"] = "*"
return response
在 Next.js 端,确保您的获取请求具有您拥有的凭据:“include”集。
这使得 CORS 策略能够传递会话 cookie。如果没有它,默认情况下跨域请求将被阻止发送或接收 cookie。
请告诉我这是否有助于解释问题!关键是在 Django 和 Nextjs 端正确启用 CORS 策略的凭据。