DJANGO VUE3 跨域CSRF问题刨坑

文章目录

  • 前言
  • 1.跨域问题
    • 第一步,安装cors的扩展包
    • 第二步,导入应用
    • 第三步,插入中间件
    • 第四步,允许发送cookie
    • 第五步,设置白名单:
    • 第六步,设置允许的请求方法
    • 第七步,设置允许的其请求头
    • 第八步,测试
  • 2.CSRF问题和Cookie
    • 第一步,VUE的main.ts设置
    • 第二步,通过get请求先获取csrftoken
    • 第三步,请求中带上CSRFTOKEN
  • 结语

前言

不行,我必须要总结一下,搞了两天,都在处理跨域的问题。
看到尤大的那句直接学VUE3就好,开始了VUE3+TS的刨坑之路,只能说不懂英语的程序员实在是太吃亏了,中文世界的VUE3资料十分零散,好难推进。

一来是就遇到以下三个问题:
1.跨域问题
2.csrf问题
3.cookie问题
问题本质上是为了完成Django的CSRF验证,但是三个问题互相纠缠非常麻烦。

1.跨域问题

由于是前后端分离的测试项目,目前还不知道最后部署是什么样的,所以我的Django项目开了3000的端口,而Vue这边的测试端口用的是8080,这样就触发了我们的大坑,跨域问题。
跨域问题的整体解决思路可以查看下面这个大大的文章:
https://juejin.cn/post/6844903536442998791
解决方法是使用CROS来处理相关问题,具体原理学习阮老师的文章(强烈建议通读这个文章):
http://www.ruanyifeng.com/blog/2016/04/cors.html
但是他没有给具体的解决方法,基本思路是通过修改Django部分的设置来处理,我操作起来大概是几个部分

第一步,安装cors的扩展包

python -m pip install django-cors-headers

第二步,导入应用

# settings.py
INSTALLED_APPS = [
	...
    # 处理跨域
    'corsheaders',
]

第三步,插入中间件

# settings.py
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

第四步,允许发送cookie

# settings.py
CORS_ALLOW_CREDENTIALS = True

第五步,设置白名单:

# settings.py
# CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST =(
    'http://127.0.0.1:8080',
    'http://localhost:8080',
)

阮老师的文章里面有提到:

如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号

但是经过我的测试,他这里的设置为CORS_ORIGIN_ALLOW_ALL 的情况下依旧可以获取Cookie不知道具体原因是什么,但是从安全角度出发,还是设置白名单比较安全。
值得注意的是,这里就算你设置了白名单可能还有一些问题会到会导致你无法取到Cookie,具体请看后面Cookie问题的那一节。

第六步,设置允许的请求方法

# settings.py
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

第七步,设置允许的其请求头

# settings.py
CORS_ALLOW_HEADERS = (
    # '*',该通配符无效
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

在这一步我卡了很久,一开始我这里是设置的星号*,以为是通配符。结果这个*并不能通配,比如后面的x-csrftoken就无法识别我的CSRF的KEY,导致我一直报错,后来是把星号去掉换成各个具体的头名名单才能通过。
在这里插入图片描述

Access to XMLHttpRequest at 'http://127.0.0.1:3000/login_action/' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: Request header field x-csrftoken is not allowed by Access-Control-Allow-Headers in preflight response.

第八步,测试

后端设置好后就可以通过POSTMAN来测试一下接口能不能使用,注意这里请用GET接口来做测试,因为GET接口是不用监测CSRF的,能正常返回的话我们可以看一下cookie这个返回值,里面应该会有我们的csrftoken,接下来就要搞这个。。。

2.CSRF问题和Cookie

CSRF和Cookie太紧密了,我就和在一点说了。
CSRF问题大家用过django的应该非常熟悉了,如果是Django自带的模板我们可以直接将数据渲染在模板里面,然后提交表单的时候带在参数里面就可以了。而在跨域的VUE上这事变得异常痛苦。
总的来说,你需要先通过一次GET请求获得附带在Cookie里面的CSRFTOKEN。然后再通过在POST请求中带上这个TOKEN来通过Django的CSRF认证。

第一步,VUE的main.ts设置

首先你要解决第一大点中的跨域问题,解决了并通过GET测试看到Cookie后再继续。
接下来你需要在main.ts中做好相应的配置保证获取到服务器的Cookie。

//main.ts
import axios from "axios";
//axios.defaults.baseURL = 'http://127.0.0.1:3000'
//这两个值好像默认就是这样了,所以不重要,重点是最后一个设置
axios.defaults.xsrfCookieName = 'csrfmiddlewaretoken'
axios.defaults.xsrfHeaderName = 'X-XSRF-TOKEN'
//重点!!!设置请求获取cookie
axios.defaults.withCredentials = true

如果我们没有做这个设置的话

withCredentials = true

就算后台允许发送cookie,还是不会收到cookie具体原理可以看阮老师的文章。

第二步,通过get请求先获取csrftoken

CSRF跨域是不会自动生成csrftoken的(深坑,之前POST后端报错csrf not set 就是这个原因)
post请求前必须先get一次产生token
from:https://www.cnblogs.com/linxizhifeng/p/8995077.html

如上所述,你需要先通过一次get操作来读取cookie里面的CSRF-KEY

axios.get('/login_action/',{withCredentials: true})
        .then((response) => {
          console.log(response)
          axios.defaults.headers['X-CSRFToken'] = getCsfrKey()
        })

这里我遇到一个坑:
cookie的同源问题
如果你有看我前面的那个测试你就能看出来Django返回的scrftoken是附在Cookie里面的,我们需要操作Cookie去取。但是一开始设置完我死活看不到Cookie,可是在前面POSTMAN测试里我们是可以看到Cookie的。
通过在console里面输入:

javascript:alert(document.cookie)

结果依旧是空,问题出在哪里呢?
其实是Cookie保存的同源策略的问题。
在VUE编译完后有两个地址可以点,我习惯去访问那个localhost的地址,如下图。
在这里插入图片描述
出现问题的原因如下图,简单来说,你的源地址要和你访问的这个地址同源。
从我的例子来说,我用
localhost -> 127.0.0.1
就不行,要用
127.0.0.1 -> 127.0.0.1
就可以了,因为服务器看你不会是一个叫做localhost的地址,而是127的具体地址,所以你本身的地址也要和127的相同,不然就没办法保存Cookie。
from:https://segmentfault.com/q/1010000009287272
在这里插入图片描述

第三步,请求中带上CSRFTOKEN

取到CSRF的KEY后我们有三种方式发送给后台:
1.直接在axios里面全局设置

axios.defaults.headers['X-CSRFToken'] = getCsfrKey()

2.在请求的头里面设置

axios.post('/login_action/',
          params,{headers:{"X-CSRFToken": getCsfrKey()}})
          .then((response) => {
            console.log(response.data)
          })

3.在参数里面设置

      let params = new URLSearchParams();
      params.append('user_name',formState.userName)
      params.append('pwd',formState.password)  
      params.append('csrfmiddlewaretoken',getCsfrKey())

我觉得还是第一种方便一点,一打开网页就可以先去获取key获取完后直接塞进axios里面,后面就都不用管了,多舒服。

这里也遇到一个坑,卡了很久。
就是跨域问题中的第七步中的允许头的问题。
问题的现象是,把带着CSRFTOKEN的POST请求上报服务器之后,Django的输出台看到的请求一直是OPTION,而不是我用的POST。
这个问题的根本就是由于跨域请求的时候,浏览器需要通过OPTION来和服务器确认自己到底能不能访问,确认过后才会发送我们的POST请求。由于后台设置的问题,一直我们请求头中的X-CSRFToken一直没办法被后台接收,导致OPTION的返回请求中没有带上我们需要的头,虽然返回code是200,但是浏览器遗留以为我们被后台跨域拒绝了,一直给我报跨域的错,后面把*给改成具体的头就OK了。

结语

CSRF的问题就暂告一段落,我要继续搬砖去了。不得不说感觉前端的设计思路和我们后端的真的差别有点大,摸起来有点左右横跳的感觉,可能前端人均大神吧。。不过从接触大前端开始感觉好像终于有点接近了。
同时继续鄙视一下百度的搜索机制,真的,这种技术类的文章内容你都不会过滤一下的?抄来抄去显示都是同一个文章,不能搭梯子的开发是真的难受。
我是跨域跨到蛋疼的llsxily,你可以叫我橘子。

热门文章

暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法,在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较,从而确定目标数是在中间数的左边还是右边,将查…
暂无图片
编程学习 ·

GMX 命令分类列表

建模和计算操作命令: 1.1 . 创建拓扑与坐标文件 gmx editconf - 编辑模拟盒子以及写入子组(subgroups) gmx protonate - 结构质子化 gmx x2top - 根据坐标生成原始拓扑文件 gmx solvate - 体系溶剂化 gmx insert-molecules - 将分子插入已有空位 gmx genconf - 增加…
暂无图片
编程学习 ·

一文高效回顾研究生课程《数值分析》重点

数值分析这门课的本质就是用离散的已知点去估计整体,就是由黑盒子产生的结果去估计这个黑盒子。在数学里这个黑盒子就是一个函数嘛,这门课会介绍许多方法去利用离散点最大化地逼近这个函数,甚至它的导数、积分,甚至微分方程的解。…
暂无图片
编程学习 ·

在职阿里5年,一个28岁女软测工程师的心声

简单的先说一下,坐标杭州,14届本科毕业,算上年前在阿里巴巴的面试,一共有面试了有6家公司(因为不想请假,因此只是每个晚上去其他公司面试,所以面试的公司比较少) ​ 编辑切换为居中…
暂无图片
编程学习 ·

字符串左旋c语言

目录 题目: 解题思路: 第一步: 第二步: 第三步: 总代码: 题目: 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符…
暂无图片
编程学习 ·

设计模式--观察者模式笔记

模式的定义与特点 观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&#xf…
暂无图片
编程学习 ·

睡觉突然身体动不了,什么是睡眠痽痪症

很多朋友可能有这样的体验,睡觉过程中突然意识清醒,身体却动弹不了。这时候感觉非常恐怖,希望旁边有一个人推自己一下。阳光以前也经常会碰到这样的情况,一年有一百多次,那时候很害怕晚上到来,睡觉了就会出…
暂无图片
编程学习 ·

深入理解C++智能指针——浅析MSVC源码

文章目录unique_ptrshared_ptr 与 weak_ptrstd::bad_weak_ptr 异常std::enable_shared_from_thisunique_ptr unique_ptr 是一个只移型别(move-only type,只移型别还有std::mutex等)。 结合一下工厂模式,看看其基本用法&#xff…
暂无图片
编程学习 ·

@TableField(exist = false)

TableField(exist false) //申明此字段不在数据库存在,但代码中需要用到它,通知Mybatis-plus在做写库操作是忽略它。,.
暂无图片
编程学习 ·

Java Web day15

第十二章文件上传和下载 一、如何实现文件上传 要实现Web开发中的文件上传功能,通常需要完成两步操作:一.是在Web页面中添加上传输入项;二是在Servlet中读取上传文件的数据,并保存到本地硬盘中。 需要使用一个Apache组织提供一个…
暂无图片
编程学习 ·

【51nod 2478】【单调栈】【前缀和】小b接水

小b接水题目解题思路Code51nod 2478 小b接水 题目 输入样例 12 0 1 0 2 1 0 1 3 2 1 2 1输出样例 6解题思路 可以发现最后能拦住水的都是向两边递减高度(?) 不管两个高积木之间的的积木是怎样乱七八糟的高度,最后能用来装水的…
暂无图片
编程学习 ·

花了大半天写了一个UVC扩展单元调试工具

基于DIRECTSHOW 实现的,用的是MFC VS2019. 详见:http://www.usbzh.com/article/detail-761.html 获取方法 加QQ群:952873936,然后在群文件\USB调试工具&测试软件\UVCXU-V1.0(UVC扩展单元调试工具-USB中文网官方版).exe USB中文网 USB中文…
暂无图片
编程学习 ·

贪心(一):区间问题、Huffman树

区间问题 例题一:区间选点 给定 N 个闭区间 [ai,bi]请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数 N,表示区间数。 接下来 …
暂无图片
编程学习 ·

C语言练习实例——费氏数列

目录 题目 解法 输出结果 题目 Fibonacci为1200年代的欧洲数学家,在他的着作中曾经提到:「若有一只免子每个月生一只小免子,一个月后小免子也开始生产。起初只有一只免子,一个月后就有两只免子,二个月后有三只免子…
暂无图片
编程学习 ·

Android开发(2): Android 资源

个人笔记整理 Android 资源 Android中的资源,一般分为两类: 系统内置资源:Android SDK中所提供的已经定义好的资源,用户可以直接拿来使用。 用户自定义资源:用户自己定义或引入的,只适用于当前应用的资源…
暂无图片
编程学习 ·

零基础如何在短时间内拿到算法offer

​算法工程师是利用算法处理事物的职业 算法(Algorithm)是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。 如果一个算法有缺陷,或不适合于某个问题,执…
暂无图片
编程学习 ·

人工智能:知识图谱实战总结

人工智能python,NLP,知识图谱,机器学习,深度学习人工智能:知识图谱实战前言一、实体建模工具Protegepython,NLP,知识图谱,机器学习,深度学习 人工智能:知识图…
暂无图片
编程学习 ·

【无标题】

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…