获取 API 请求工作正常。发布请求返回缺少 CSRF 令牌,但它在那里

问题描述 投票:0回答:1

我有一个 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,那么为什么不发送它呢?

django-rest-framework vuejs3
1个回答
0
投票

尝试像这样更改您的注销功能:

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);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.