如何在Django的ajax POST中返回新的csrf标记?

时间:2015-10-05 16:44:40

标签: ajax django django-templates django-csrf

我有这个简单的Like按钮,当与@csrf_exempt一起使用时效果很好:

模板

<p id="like_count"> {{ topic.likes }}</p> 
<span data-type="topic" title="Like">       {% csrf_token %}
 <i class="fa fa-thumbs-up" id="liket" name="{{topic.id}}">  

Ajax

$(function(){
$('#liket').click(function(){
      $.ajax({
               type: "POST",
               url: "/like/",
               data: {
               'topic_id': $(this).attr('name'), 
               'csrfmiddlewaretoken': '{{csrf_token}}'
               },
               success: tlikeSuccess,
               dataType: 'html'               
                });
    });

});
function tlikeSuccess(data, textStatus, jqXHR)
{
    $('#like_count').html(data);
}

和观点:

#@csrf_exempt 
def topic_like(request):

    args = {}
    if request.method == 'POST':

        user = request.POST.get('user')
        lu= request.user #User.objects.get(username= user)
        topic_id = int(request.POST.get('topic_id'))

        try:
            liked_topic = Topic.objects.get(id = topic_id)
        except:
            liked_topic = None  

        if TopicLike.objects.filter(liker=request.user.id, topic=topic_id).exists():

            liked_topic.likes -=1
            liked_topic.save()
            TopicLike.objects.filter(topic=topic_id, liker=request.user.id).delete()

        else:            
            liked_topic.likes +=1
            liked_topic.save()
            newliker = TopicLike(topic=topic_id, liker=request.user.id)
            newliker.save()          


    #args.update(csrf(request))
    args['likes'] = str(liked_topic.likes)
    return render(request, 'ajax_like.html', args)  

但是,我不喜欢忽略CSRF的这种解决方法,因为它可能很脆弱。 另一方面,我无法将新的CSRF令牌返回给模板,因此我感谢您将CSRF集成到此按钮中的提示。

2 个答案:

答案 0 :(得分:4)

Django在其docs中定义了实际设置AJAX请求的头,同时保护CSRF令牌不会在jQuery 1.5.1和更新版本中使用settings.crossDomain发送到其他域。

获取令牌:

// using jQuery
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

在标题中设置CSRFToken:

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

同时尝试使用此方法在此SO link.

上给出的每个AJAX请求中嵌入CSRF令牌
$(function () {
    $.ajaxSetup({
        headers: { "X-CSRFToken": getCookie("csrftoken") }
    });
});

答案 1 :(得分:0)

您可以使用javascript手动添加csrf令牌。

https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax