Vue+Django axois的post请求CSRF问题的解决
近期有个报表展示网页的小项目。
我试着用前后端分离的方式搭建,在数据交互这里遇到了403 CSRF cookie not set的问题。
经过一番配置,已解决。
以下为具体解决方法。
Django的csrftoken有两种验证方式,
一种为在ajax中传输的参数中添加csrfmiddlewaretoken的方式来实现,
另一种为在请求头中添加X-CSRFToken的方式。
我这里采用的是第二种。
首先,封装axios。
打开你的vue项目,在你喜欢的文件夹下新建xxxx.js文件(可以是static也可以是assets)
如何封装大家可以按自己喜好来,这里主要介绍解决CSRF的问题(黄色代码片段)
import axios from 'axios' import getUrl from './getPath.js' //状态检测 let stateDetection = (data, callback) => { let status = data.status_code; switch (status) { case 102: break; case 103: alert(data.content); break; case 404: window.location.href = data.url; break; } } // 截取出csrftoken let getCookie = function(cookie){ let reg = /csrftoken=([\w]+)[;]?/g return reg.exec(cookie)[1] } // 统一给post添加头请求 axios.defaults.withCredentials=true axios.interceptors.request.use( function(config) { // 在post请求前统一添加X-CSRFToken的header信息 let token = document.cookie; if(token && config.method == 'post'){ config.headers['X-CSRFToken'] = getCookie(token); } return config; }, function(error) { // Do something with request error return Promise.reject(error); } ) export default { Get: (config) => { axios.get(getUrl(config.url), { params: config.params }).then((res) => { stateDetection(res); config.callback && config.callback(res) }) }, Post: (config) => { axios.post(getUrl(config.url), { params: config.params, }).then((res) => { stateDetection(res); config.callback && config.callback(res); }) }, }
在main.js引入封装好的内容,这里就不做多余赘述了。
接下来,Django端的配置。
前后端分离导致的跨域问题需要安装如下包
pip install django-cors-headers
安装完成后配置settings.py
INSTALLED_APPS = [ ...... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 注意该行位置 'django.middleware.common.CommonMiddleware',# 该行为原本就有的,新添的需要填在这行上面 ] CORS_ALLOW_CREDENTIALS = True CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_WHITELIST = ( 'your address',# 填写发送请求端的地址 ) CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'VIEW', ) CORS_ALLOW_HEADERS = ( 'XMLHttpRequest', 'X_FILENAME', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', 'Pragma', )
完成!