我有一个 Django 网站(带有标准视图),用于注册和登录。登录后,您可以转到从 Django Rest Framework 后端获取数据的 Vue 应用程序。我正在使用会话身份验证。从昨天开始,每当我发出 POST、PUT 或 DELETE 请求时,都会收到 403 错误,内容为“CSRF 失败:CSRF 令牌丢失”。但如果我查看标头,那么 cookie 就在那里,因为我在登录时收到了它。我认为 Vue (axios) 在向后端 API 发出请求时使用此 cookie?为什么这对我不起作用?
Vue main.js:
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
import axios from "axios";
import "./registerServiceWorker";
axios.defaults.baseURL = "http://localhost:8000";
axios.defaults.xsrfHeaderName = "X-CSRFToken";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.withCredentials = true;
const pinia = createPinia();
const app = createApp(App);
app.use(router);
app.use(pinia);
app.mount("#app");
Django 设置:
CORS_ALLOWED_ORIGINS = [
"http://localhost:8080",
"http://localhost:8000",
"http://127.0.0.1:8080",
"http://127.0.0.1:8000",
"http://localhost:file",
"http://192.168.1.40:8080",
]
CORS_ALLOW_CREDENTIALS = True
SESSION_COOKIE_SAMESITE = None
CSRF_TRUSTED_ORIGINS = [
"http://localhost:8080",
"http://*.127.0.0.1",
"http://127.0.0.1:8080",
"http://192.168.1.40:8080",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
"DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",),
"DEFAULT_PARSER_CLASSES": [
"rest_framework.parsers.MultiPartParser",
"rest_framework.parsers.JSONParser",
],
"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
}
对于所有 POST、PUT、DELETE 请求,我都会收到 403,但这是我尝试向以下位置发出发布请求的一个视图:
class LogoutView(APIView):
def post(self, request):
if request.user.is_authenticated:
logout(request)
return Response({"message": "Logged out successfully"}, status=status.HTTP_200_OK)
else:
return Response({"message": "No user is authenticated"}, status=status.HTTP_400_BAD_REQUEST)
这是向后端发出请求的 Vue 代码:
async function logOut() {
try {
const response = await axios.post("/api/v1/users/logout/");
store.loggedIn = false;
store.userID = 0;
localStorage.removeItem("account");
window.location.href = "http://localhost:8000";
} catch (error) {
console.log(error);
}
}
以下是请求标头:
Accept
application/json, text/plain, */*
Accept-Encoding
gzip, deflate, br
Accept-Language
en-US,en;q=0.5
Cache-Control
no-cache
Connection
keep-alive
Content-Length
0
Cookie
csrftoken=C4T69wWvlRZ8HeLx80bAFBrHMoRJAUsT; sessionid=lu80tjrcqwqgs14i4qgowob37ejbk90k
Host
localhost:8000
Origin
http://localhost:8080
Pragma
no-cache
Referer
http://localhost:8080/
Sec-Fetch-Dest
empty
Sec-Fetch-Mode
cors
Sec-Fetch-Site
same-site
User-Agent
Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0
我认为浏览器存储中的cookie是必须发送到后端的cookie,那么为什么不发送它呢?
尝试像这样更改您的注销功能:
async function logOut() {
try {
// Get the CSRF token from the cookie
const csrfToken = 'place actual csrf token here..maybe load from cookie';
// Set the CSRF token in the Axios headers
axios.defaults.headers.common['X-CSRFToken'] = csrfToken;
// Make the logout request
const response = await axios.post("/api/v1/users/logout/");
// Reset local state and redirect
store.loggedIn = false;
store.userID = 0;
localStorage.removeItem("account");
window.location.href = "http://localhost:8000";
} catch (error) {
console.error(error);
}
}