使用Node.js+Supertest/Supertest-Session复现Django/React应用Python登录脚本时缺失CSRF Cookie的问题
Troubleshooting Missing CSRF Token in Supertest/Supertest-Session for Django/React App
I’ve run into similar headaches testing Django apps with Supertest, so let’s break down the most likely fixes for your issue:
- Always trigger a GET request first to fetch the CSRF token
Django doesn’t automatically send thecsrftokencookie in POST requests—you need to first hit a route that triggers the CSRF middleware, like your login page’s GET endpoint or Django’s built-in/csrf/view (if enabled). Unlike Postman/Curl where you might manually handle this step first, Supertest doesn’t do this automatically by default.
Here’s a practical example of how to structure this flow with Supertest-Session:
const request = require('supertest'); const session = require('supertest-session')('http://localhost:8000'); // Replace with your Django app URL test('successful login with CSRF token', async () => { // Step 1: Fetch the CSRF token via a GET request to the login page const getLoginPage = await session.get('/accounts/login/'); // Parse the csrftoken from the Set-Cookie header const csrfToken = getLoginPage.headers['set-cookie'] .find(cookie => cookie.startsWith('csrftoken=')) .split(';')[0] .split('=')[1]; // Step 2: Use the extracted token to send your login POST request const loginResponse = await session.post('/accounts/login/') .set('X-CSRFToken', csrfToken) // Django expects this header for CSRF validation .send({ username: 'your-test-user', password: 'your-test-password' }); // Verify login success (adjust status code to match your app's behavior) expect(loginResponse.statusCode).toBe(302); });
- Match request headers to what Django expects
Django’s CSRF middleware sometimes skips setting the cookie if the request headers don’t resemble a typical browser request. Supertest uses minimal default headers, so try adding common browser headers to your GET request:
const getLoginPage = await session.get('/accounts/login/') .set('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8') .set('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36');
Check your Django settings for CSRF restrictions
- If
CSRF_COOKIE_SECUREis set toTruein your test environment, Django will only send the CSRF cookie over HTTPS. For local testing, set this toFalse. - Ensure your test domain (usually
localhost) is listed inCSRF_TRUSTED_ORIGINSif you’ve configured this setting—Django won’t send the CSRF cookie to untrusted origins.
- If
Simplify cookie parsing with a library
Instead of manually splitting theSet-Cookieheader, use thecookienpm package to make parsing cleaner:
const cookie = require('cookie'); // ... const cookies = cookie.parse(getLoginPage.headers['set-cookie'].join('; ')); const csrfToken = cookies.csrftoken;
The most common culprit here is forgetting that initial GET request—Django won’t send the CSRF cookie unless it detects a request that needs it (like a GET to a page with a form).
内容的提问来源于stack exchange,提问作者user2072187
相关产品推荐
相关产品推荐

