vue+django前后端分析解决csrf token问题

vue-resource post数据

阅读django CsrfViewMiddleware源码可知,csrftoken可以放在请求参数(csrfmiddlewaretoken)里面或者请求头(X-CSRFToken)里:

     # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')    
1 this.$http.post('/someUrl',data, [options]).then(function(response){
2     // 响应成功回调
3 }, function(response){
4     // 响应错误回调
5 });

vue-resource 向后端请求api, 公司的后台是用Django 开发的,Django为了防止跨站请求伪造,即csrf攻击,提供了CsrfViewMiddleware中间件来防御csrf攻击。

我们在html 页面里加入{% csrf %}来让django渲染出一个csrf的标签 
(如果是form 提交表单的话,我们要把这个标签加在form标签内,如果是用xhr提交的话写在html页面里就可以了)

不写在form 表单内,但是实现效果是一样的,我们都需要在post 的表单中提供csrftoken我们在vue里要传送的的data 里要加上csrf的key

data{
    csrfmiddlewaretoken: '{{ csrf_token }}' 
}

这样django解析表单时会解析到csrf_token, 我们post的数据就不会遇到403 forbidden了。

其实这样是投机取巧的行为,这样虽然django 也能识别,但是遇到复杂的数据时就不行了,比如数组,vue-resource post 数组的时候, 因为我之前在post的option里加了一个option {emulateJSON: true},这样vue-resource 在post数据时,会把data 转换成 application/x-www-form-urlencoded表单格式,但是这样的话,post 的数组就会被解析成arrry[0]item 这样的话,后端是不识别的,会报错。

解决方式查到是把csrftoken 放在报头里,data 传数据,具体解决方式是加一条

Vue.http.headers.common['X-CSRFToken'] = $("input[name='csrfmiddlewaretoken']").val()

其中$("input[name='csrfmiddlewaretoken']").val() 是取django 的{% csrf %}在模板解析后生成的input里的csrftoken。

其中报头的话django 在后台解析的时候会自动加上HTTP_的前缀,所以说我们的报头是 X-CSRFToken就可以了。

另附一片参考博客地址:https://www.cnblogs.com/linxizhifeng/p/8995077.html

猜你喜欢

转载自www.cnblogs.com/wangwei916797941/p/9283776.html