django框架下用ajax发送post请求403forbidden解决方法

方法来自【Python建站】12.用户验证登录和官方文档,这里对方法进行总结方便参考和日后复习
环境:Django2.1+VueJS
插件:前端:reqwest 后端:Django REST framework
适用于使用

问题引入

在网站中加入登录验证模块时,使用ajax向后端提交数据
前端发送请求模块:

userLogin:function(){
     var self = this
     reqwest({
         url:'/api/index',
         method:'post',
         type:'json',
         data:{
             username: self.username,
             password: self.password,
         },
          //获取验证结果
         success:function(data){
             console.log(data)
         },
         //打印错误信息
         error:function(error){
             console.log(error)
         }
         
     })
 },

后端验证模块:(去除了一些与本文无关内容)

@api_view(['GET', 'POST'])
def indexData(request):
# 验证用户密码是否正确
if request.method == 'POST':
    # print('ok')

    # post来的信息
    username = request.POST['username']
    password = request.POST['password']
    # 是否通过了User login的验证
    user = authenticate(username=username, password=password)
    print(user)  # 正确返回user 错误返回none
    if user != None: 
        login(request, user)
        return Response({'loginType': 'ok'})

目的是在使用后端验证后,向前端返回验证{‘loginType’: ‘ok’}的结果,但在提交post请求后出现了问题,POST请求返回了403 Forbidden的Status Code

status: 403
statusText: "Forbidden

同时后端打印出了这样的错误,说明POST请求被拒绝了

Forbidden: /api/index
[27/May/2019 12:21:04] "POST /api/index HTTP/1.1" 403 58

问题来源:Django中的CSRF防御机制阻止了前端POST请求提交,CSRF原理及应用参考Django中CSRF原理及应用详解

解决方法

通过对CSRF原理的了解,我们知道csrf验证其实是对http请求中一段随机字符串的验证用来防止CSRF攻击,所以我们需要在前端发送POST请求时携带这串随机字符通过Django的验证。在查询官方文档后发现在input标签前使用{% csrf_token %}就可以获得token通过Django的验证,但在这里我们使用了Vuejs来接管前端,Django的解决方法在这里并不生效。

由于我们是使用Vuejs来发送POST请求,所以我们需要在VueJS发送请求的模块下加入有CSRF的token的头部信息,在发送请求的模块中加入:

 headers:{
     "X-CSRFTOKEN":csrftoken
 },

那么这个csrftoken又要怎么获得呢?在这里使用了js-cookie,下载js文件放入项目的js文件夹。
在html的头部加入

<script src="{% static 'js/js.cookie.js' %}" charset="utf-8">script>

同时在body的最后加入

 <script type="text/javascript">
     var csrftoken = Cookies.get('csrftoken')
     console.log(csrftoken)
 script>

现在保存,打印一下csrftoken,可以看到这样的一串随机字符,这就是csrf的token

BE7lgnhQ2giehLcTH9ydBotsxQhQKOIg32bdnczb8LvUjCWpGW3ndCnYnu30xmMl

现在再点击登录,可以发现不会被CSRF拦截了,成功打印出{loginType: “ok”}的信息

你可能感兴趣的:(Django)