Django+Graphene对接Nuxt前端POST请求403 Forbidden问题求助
你遇到的问题核心是CSRF令牌传递异常,再加上请求格式和配置的小疏漏,导致前端请求被Django的CSRF防护拦截了。我帮你梳理几个关键修复点:
1. 修正Django的CORS配置错误
你的settings.py里CORS_ORIGIN_WHITELIST设置成了字符串,但Django要求它是数组类型,这会直接导致CORS验证不通过,进而影响CSRF令牌的正常传递:
# settings.py CORS_ORIGIN_WHITELIST = [ 'http://localhost:3000', 'http://127.0.0.1:3000' # 同时添加这两个地址,避免不同访问路径的兼容性问题 ] CORS_ALLOW_CREDENTIALS = True CSRF_USE_SESIONS = False CSRF_COOKIE_HTTPONLY = False CSRF_COOKIE_SAMESITE = 'Lax' # 建议改成Lax,None在部分浏览器可能存在兼容性问题
2. 修复Axios拦截器的代码问题
你在plugins/axios.js里的代码有两处明显问题:await用在onRequest上完全没必要(onRequest本身不需要异步),而且配置顺序和赋值逻辑可能导致Content-Type和X-CSRFToken变成undefined。修改成这样:
// plugins/axios.js export default function ({ $axios, app }) { $axios.onRequest((config) => { // 先固定设置Content-Type,避免被后续操作覆盖 config.headers.common['Content-Type'] = 'application/json' // 正确获取并设置CSRF令牌 const csrfCookie = app.$cookies.get('csrftoken') if (csrfCookie) { config.headers.common['X-CSRFToken'] = csrfCookie } // 配置CSRF相关的Cookie和Header名称 config.xsrfCookieName = 'csrftoken' config.xsrfHeaderName = 'X-CSRFToken' console.log('Request config:', config) }) }
另外要确保你已经安装并注册了@nuxtjs/axios和cookie-universal-nuxt插件,否则app.$cookies会无法正常使用。
3. 修正GraphQL请求的数据格式
你的store/contact.js里把AddMessage直接作为data发送,但GraphQL期望的是包含query、variables、operationName的JSON对象,而且你的variables是字符串格式,还多了一个多余的逗号,这都会导致请求解析失败:
首先修改queries/contact.js:
// queries/contact.js export const AddMessage = { query: ` mutation AddContact($input: AddMessageInput!){ addMessage(input: $input){ message{ name email body terms } } } `, variables: { "input": { "name": "test", "email": "test@test.com", "body": "test", "terms": true } }, operationName: 'AddMessage' }
然后修改store/contact.js的请求逻辑:
// store/contact.js import { AddMessage } from '../queries/contact.js' export const actions = { async send() { try { // 先发送一个GET请求获取CSRF令牌(如果前端还未持有该Cookie) await this.$axios.get('/api/') const message = await this.$axios({ url: 'api/', method: 'POST', data: AddMessage // 现在是符合GraphQL要求的JSON格式 }) console.log('Request success:', message) } catch (error) { console.error('Request error:', error.response) } } }
4. 确保CSRF令牌的正确传递
Django的CSRF防护要求请求必须携带从Cookie获取的令牌,所以在发送POST请求前,先发送一个GET请求到GraphQL端点,让后端主动设置csrftoken Cookie,这样前端才能拿到有效的令牌用于后续POST请求。
做完这些修改后,再测试请求,应该就能解决403错误了。
内容的提问来源于stack exchange,提问作者Ionut

