Vue.js前端CSRF返回异常问题咨询(附Django登录API代码)
Hey there, let's work through this CSRF issue you're hitting. Looking at your code, the first red flag is that you've commented out the @ensure_csrf_cookie decorator—this is critical for getting the CSRF token to your Vue frontend. Let's break down the fixes step by step:
1. Re-enable the @ensure_csrf_cookie Decorator
Django won't automatically set a CSRF cookie for API views that return JSON responses (like your UserLoginAPIView GET method). The @ensure_csrf_cookie decorator forces Django to send the csrftoken cookie along with the GET response, which your frontend needs to authenticate the POST request.
Update your view code like this:
from django.views.decorators.csrf import ensure_csrf_cookie from django.utils.decorators import method_decorator class UserLoginAPIView(APIView): permission_classes = [AllowAny] serializer_class = UserLoginSerializer @method_decorator(ensure_csrf_cookie) # Uncomment and use method_decorator for class-based views def get(self, request, format=None): return Response(status=status.HTTP_200_OK) def post(self, request, *args, **kwargs): data = request.data serializer = UserLoginSerializer(data=data) if serializer.is_valid(): new_data = serializer.data user = User.objects.get(**new_data) # Rest of your login logic here...
2. Configure Vue.js to Send the CSRF Token
Your Vue app needs to grab the csrftoken cookie from the browser and include it in the X-CSRFToken header for all POST requests. If you're using Axios (the most common HTTP client for Vue), add this configuration to your app's entry file (e.g., main.js):
First, install js-cookie to easily access cookies (optional but cleaner):
npm install js-cookie
Then set up Axios:
import Vue from 'vue' import axios from 'axios' import Cookies from 'js-cookie' // Configure Axios to automatically use the CSRF token axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = 'X-CSRFToken' // Or use a request interceptor for more control axios.interceptors.request.use(config => { config.headers['X-CSRFToken'] = Cookies.get('csrftoken') return config }) Vue.prototype.$axios = axios
3. Fetch the CSRF Cookie Before Sending the Login POST Request
Before submitting the login form, your Vue component should first make a GET request to your login API endpoint to retrieve the CSRF cookie. Here's an example login method:
export default { data() { return { loginForm: { username: '', password: '' } } }, methods: { async handleLogin() { try { // First, get the CSRF cookie await this.$axios.get('/api/login/') // Then send the login POST request const response = await this.$axios.post('/api/login/', this.loginForm) // Handle successful login (e.g., store token, redirect) console.log('Login successful:', response.data) } catch (error) { console.error('Login failed:', error.response.data) } } } }
4. Verify Django's CSRF Middleware is Enabled
Double-check your Django settings.py to ensure the CSRF middleware is present in the MIDDLEWARE list—it should be there by default, but sometimes it gets removed accidentally:
MIDDLEWARE = [ # ... other middleware ... 'django.middleware.csrf.CsrfViewMiddleware', # ... other middleware ... ]
5. Handle Cross-Origin Requests (If Applicable)
If your Vue app is running on a different domain/port than your Django backend (e.g., Vue on localhost:8080, Django on localhost:8000), you need to configure CORS to allow credentials:
- Install
django-cors-headers:
pip install django-cors-headers
- Add it to your Django
settings.py:
INSTALLED_APPS = [ # ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # Place this early in the list # ... other middleware ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:8080", # Your Vue app's URL ] CORS_ALLOW_CREDENTIALS = True # Critical for allowing cookies across domains
That should resolve the CSRF exception you're seeing. The key pieces are ensuring Django sends the CSRF cookie, your Vue app retrieves it, and includes it in the POST request headers.
内容的提问来源于stack exchange,提问作者Roman Nozhenko

