
这次要实现的功能是:点击【身份证ID】生成指定数量的身份证号

1. 前端main_page.vue相关代码编写
<script>import axios from 'axios'import Qs from 'qs'export default {name: "main_page",data() {return {num1: null,num2: null,info: null,}},methods: {create_data(event) {if (event.target.id === "b01") { //通过event.target.id,获取浏览器监听到的点击事件,并查看点击元素的id,通过比对id值判断触发哪个请求axios({url: "http://localhost:8000/create_data/phone" //如果不指定method,默认发送get请求}).then(res => {this.info = res.dataconsole.log(res)})} else if (event.target.id === "b02") {console.log('输入的num1='+this.num1)let payload1 = {num: this.num1,}axios({method: "post",headers: {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',},data: Qs.stringify(payload1), //发送post请求,使用data关键字接收请求参数url: "http://localhost:8000/create_data/id"}).then(res => {this.info = res.dataconsole.log(res)})} else if (event.target.id === "b03") {let payload = {num: this.num2}console.log(payload)axios({method: "get",params: payload, //发送get请求,使用params关键字接收请求参数url: "http://localhost:8000/create_data/name"}).then(res => {this.info = res.dataconsole.log(res)})}},},}</script>
method,指明了请求方法为 post;headers,添加请求头,请求头中加了一个 Content-Type,为 application/x-www-form-urlencoded; charset=UTF-8;data,添加携带的参数,这里对参数做了一个处理,使用 Qs.stringify(payload1)对payload进行了序列化处理(如果是application/x-www-form-urlencoded格式的数据,必须要做这个处理,不然django会获取不到请求body中的参数)
2. 后端代码
def create_id(num):"""生成身份证"""identity_ids = [fake.ssn() for i in range(int(num))]return " ".join(identity_ids)@require_http_methods(['GET', 'POST'])def id(request):num = request.POST.get("num") # "Content-type","application/x-www-form-urlencoded"print(num)if num == "" or num is None:data1 = create_id(5)else:data1 = create_id(num)return HttpResponse(data1)
post请求,如果请求头Content-type=application/x-www-form-urlencoded,可以使用request.POST.get("num"),获取请求携带的参数
ok,到这里先试一下看看有没有正常得到响应,页面点击按钮后如下

CORS_ALLOW_CREDENTIALS = True # 允许携带cookie
然后再次发起请求,得到如下结果,仍然报错了

通过查资料得知,这个是django特意加的一个csrf认证,当发送post请求,向服务器提交数据时都要做这个验证,很蛋疼~~
为了解决这个问题,我在网上冲浪了很久很久,终于找到了2个解决方法
解决django-csrf认证-方法1
最简单的方式就是关闭这个验证,把相关配置注释掉,即可跳过认证,自由的发送post请求(如果是自己学习的话,可以采用这个方式,以防心态炸裂,可以愉快地进行后续的学习~)
打开settinngs.py,找到如下代码,把我标记的那一行注释即可
MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','corsheaders.middleware.CorsMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware', # 注释这一行可以去掉csrf验证'django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',]
解决django-csrf认证-方法2
from django.middleware.csrf import get_tokendef get_csrf_token(request):csrf_token = get_token(request) # 获取csrf_token的值return JsonResponse({'token': csrf_token})
create_data/urls.pyfrom django.urls import pathfrom . import viewsurlpatterns = [path('', views.main, name='main'),path('phone', views.phone, name='phone'),path('id', views.id,name='id'),path('name', views.name,name='name'),path('get_csrf_token', views.get_csrf_token,name='get_csrf_token'),]
2、前端axios的配置修改
打开main_page.vue
首先在script标签下添加一行代码
axios.defaults.withCredentials = true #允许跨域携带cookie信息,必须加上
在script标签下新增一个函数token(),用来调用后台生成csrftoken的函数get_csrf_token()
methods: {token() {axios.get("http://localhost:8000/create_data/get_csrf_token").then(res => {let token = res.data.tokenconsole.log("**********"+token);sessionStorage.setItem("csrf_token", token) //有些博主说把生成的token放到缓存中,然后发请求时拿这个缓存放到请求头中,我试了下这个其实并没有用,可以注释掉,因为我们不拿这个token})},create_data(event) {..................}
修改 create_data(event)函数中关于触发生成电话号码的axios请求
methods: {create_data(event) {this.token() //调用create_data()函数时,先调用token()函数,请求后台生成csrftoken// console.log("..............."+this.token());// console.log(typeof event.target.id)console.log('cookie='+document.cookie) //打印浏览器cookielet cookie = document.cookie //提取cookielet csrf_token = cookie.split("=")[1] //提取cookie中的csrftokenconsole.log('cookie_csrf_token='+cookie.split("=")[1])if (event.target.id === "b01") {............} else if (event.target.id === "b02") {console.log('输入的num1='+this.num1)let payload1 = {num: this.num1,}axios({method: "post",headers: {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8','X-CSRFToken': csrf_token,},data: Qs.stringify(payload1), //application/x-www-form-urlencoded,发送post请求,使用data关键字接收请求参数url: "http://localhost:8000/create_data/id"}).then(res => {this.info = res.dataconsole.log(res)})} else if (event.target.id === "b03") {............}}}
(1)首先在create_data()函数下添加了一行代码,来调用刚才新增的token()函数
this.token()
(2)提取浏览器生成的cookie
let cookie = document.cookie // 通过document.cookie提取cookielet csrf_token = cookie.split("=")[1] //提取cookie中的csrftoken
这个cookie应该是django服务器向客户端发送的,通过它来完成csrf验证,post请求必须拿到cookie中的csrftoken然后跟着请求一起发送才行!
(3)最后在headers中加一行
'X-CSRFToken': csrf_token

看一下请求的详细内容

可以看到,左图的请求中没有携带Cookie,而我们的csrf token是通过document.cookie来获取,所以左图中的X-CSRFToken为空;
网上有人说,可以把后台生成的csrftoken直接赋给请求头中的 X-CSRFToken,我试了一下并不行,还是会提示403Forbidden;


发post请求时,这里会自动多出一个cookie,也就是csrftoken
可以自己试一下,如果把这个cookie删掉,发post请求就会报 403Forbidden
如果按照上述配置好的话,每次触发这个请求时,都会在这里自动生成一个cookie,猜测是Django自动发给客户端的
然后客户端需要携带这个cookie才能提高django的csrf验证
当然,如果不按照上述配置,例如 没有配置 axios.defaults.withCredentials = true 或者 前端没有调用后台生成csrftoken的方法,触发post请求时,django服务器便不会发给客户端这个cookie
网上也有博主说可以在axios请求中添加 withCredentials: true,如下形式
axios({withCredentials: true,method: "post",headers: {......}


喜欢记得来一个






