前后端分离项目中Vue.js如何创建存储csrftoken的meta标签?
我明白你想要在Django+Vue的前后端分离架构里,实现类似Laravel那种通过meta标签存储CSRF Token的功能——其实核心思路是让前端能拿到Django生成的CSRF Token,然后像Laravel那样用meta标签存起来,再让请求自动带上它。下面分两种常见场景来一步步实现:
场景一:前端入口HTML由Django渲染(最接近Laravel的实现方式)
Laravel是通过Blade模板引擎动态生成CSRF Token的meta标签,对应到Django,我们可以把Vue的入口HTML作为Django的模板文件,用Django的模板语法来生成这个标签:
配置Django渲染Vue入口页
- 把Vue项目的
public/index.html(开发时)或者打包后的dist/index.html(生产环境)放到Django的templates目录下。 - 在Django的
urls.py中添加一个路由,用TemplateView来渲染这个模板:from django.views.generic import TemplateView urlpatterns = [ # 其他路由... path('', TemplateView.as_view(template_name='index.html'), name='frontend'), ]
- 把Vue项目的
添加CSRF Token的meta标签
在Django模板化的index.html里,直接用Django的模板变量生成meta标签,就像Laravel的{{ csrf_token() }}一样:<!-- 在index.html的<head>中添加 --> <meta name="csrf-token" content="{{ csrf_token }}">这里注意Django的模板变量是
csrf_token,不需要加括号,Django会自动填充当前请求的CSRF Token值。配置Vue自动携带Token
和Laravel默认配置axios自动读取meta标签一样,我们在Vue的main.js里配置axios,让它每次请求都带上CSRF Token:import axios from 'axios' import Vue from 'vue' // 从meta标签中获取CSRF Token const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content') // 设置axios全局请求头 axios.defaults.headers.common['X-CSRFToken'] = csrfToken // 把axios挂载到Vue原型上,方便组件中使用 Vue.prototype.$axios = axios
场景二:前端独立部署(完全前后端分离,Django不渲染前端HTML)
如果你的前端是单独部署的(比如用Nginx直接托管Vue静态文件),没法用Django模板语法生成meta标签,那我们可以通过读取Django设置的csrftoken Cookie来动态创建meta标签:
确保Django允许前端读取CSRF Cookie
检查Django的settings.py,确保CSRF_COOKIE_HTTPONLY设置为False(默认就是False,如果你修改过的话改回来),这样前端JavaScript才能读取到这个Cookie。动态创建meta标签并配置axios
在Vue的入口文件(比如App.vue的created钩子,或者main.js中)添加以下代码:import axios from 'axios' import Vue from 'vue' // 封装读取Cookie的函数 function getCookie(name) { let cookieValue = null if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';') for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim() if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)) break } } } return cookieValue } // 获取CSRF Token并动态创建meta标签 const csrfToken = getCookie('csrftoken') if (csrfToken) { // 创建meta标签并添加到<head> const metaTag = document.createElement('meta') metaTag.name = 'csrf-token' metaTag.content = csrfToken document.head.appendChild(metaTag) // 配置axios自动携带Token axios.defaults.headers.common['X-CSRFToken'] = csrfToken } Vue.prototype.$axios = axios
关键注意事项
- 跨域配置:如果前后端域名不同,一定要在Django的
settings.py中配置CSRF_TRUSTED_ORIGINS,把前端的域名加进去,比如:CSRF_TRUSTED_ORIGINS = ['https://your-frontend-domain.com'] - 请求类型:Django只会对POST、PUT、DELETE等修改类请求验证CSRF Token,GET请求不需要携带。
- Fetch替代方案:如果你用的是原生
fetch而不是axios,需要手动在请求头中添加X-CSRFToken:fetch('/api/your-endpoint', { method: 'POST', headers: { 'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').content, 'Content-Type': 'application/json' }, body: JSON.stringify(data) })
内容的提问来源于stack exchange,提问作者user7693832

