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',
)

完成!