Django:从jQuery提交表单时没有设置CSRF cookie

时间:2012-08-04 22:18:17

标签: jquery django csrf

我的jQuery功能看起来像

$("body").on("submit","form",function(e){
        // do not submit the form
        e.preventDefault();

        // handle everything yourself
        var $form = $(this);
        var title = $form.closest('.video-detail').find('.title').text();
        var entryTitle = $form.find('.input-small').val();
        console.debug(title);
        console.debug(entryTitle);

        // send the data to the server using .ajax() or .post()
        $.ajax({
            type: 'POST',
            url: 'addVideo',
            data: {video_title: title},
        }).done(function(){
            alert('done');
        });
    });

然后我的urls.py看起来像

urlpatterns = patterns('',
    url(r'^$', home),
    url(r'^done$', done, name='done'),
    url(r'', include('social_auth.urls')),
    url(r'^addVideo$', addVideo)
)

我的views.py看起来像

@login_required()
@transaction.commit_on_success
def addVideo(request):
    logging.info('add Video request - ' + str(request))
    pass

当我运行我的网络应用程序时,我使用firebug调试控制台我看到错误

my.js (line 96)
POST http://myaap.in/addVideo

403 FORBIDDEN    43ms

然后当我进一步深入了解时,我看到了

<div id="summary">
  <h1>Forbidden <span>(403)</span></h1>
  <p>CSRF verification failed. Request aborted.</p>

</div>

<div id="info">
  <h2>Help</h2>

    <p>Reason given for failure:</p>
    <pre>
    CSRF cookie not set.
    </pre>


  <p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
  <a
  href='http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ref-contrib-csrf'>Django's
  CSRF mechanism</a> has not been used correctly.  For POST forms, you need to
  ensure:</p>

  <ul>
    <li>Your browser is accepting cookies.</li>

    <li>The view function uses <a
    href='http://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext'><code>RequestContext</code></a>
    for the template, instead of <code>Context</code>.</li>

    <li>In the template, there is a <code>{% csrf_token
    %}</code> template tag inside each POST form that
    targets an internal URL.</li>

    <li>If you are not using <code>CsrfViewMiddleware</code>, then you must use
    <code>csrf_protect</code> on any views that use the <code>csrf_token</code>
    template tag, as well as those that accept the POST data.</li>

  </ul>
  • 我是Djangoweb development的新手,并不是真正明白这意味着什么
  • 请帮助我了解我需要学习什么来解决这个问题

更新

我的表单看起来像

<form class="new-playlist form-inline" onclick="event.stopPropagation()">{% csrf_token %}
     <input type="text" class="input-small">
     <button class="btn btn-danger create-playlist-button" type="submit" disabled="disabled">New</button>
</form>

更新1 Django CSRF check failing with an Ajax POST request添加代码后 我认为帖子数据为

csrfmiddlewaretoken {{ csrf_token }}
video_title The Who - Who Are You?
Source
video_title=The+Who+-+Who+Are+You%3F&csrfmiddlewaretoken=%7B%7B+csrf_token+%7D%7D

我的jQuery现在看起来像

// setting up ajaxSetup
$(function(){
    $.ajaxSetup({ 
         beforeSend: function(xhr, settings) {
             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;
             }
             if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
                 // Only send the token to relative URLs i.e. locally.
                 xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
             }
         } 
    });
});
// creating new playlist
$(function() {
    // activate "New" buttons if input is not empty
    $('form input[type="text"]').live('keyup', function() {
        var val = $.trim(this.value);
        $(this).next("button").prop('disabled', val.length === 0);
    });

    $("body").on("submit","form",function(e){
        // do not submit the form
        e.preventDefault();

        // handle everything yourself
        var $form = $(this);
        var title = $form.closest('.video-detail').find('.title').text();
        var entryTitle = $form.find('.input-small').val();
        console.debug(title);
        console.debug(entryTitle);      

        // send the data to the server using .ajax() or .post()
        $.ajax({
            type: 'POST',
            url: 'addVideo',
            data: {
                video_title: title,
                csrfmiddlewaretoken: '{{ csrf_token }}'
                },
        }).done(function(){
            alert('done');
        });
    });
});

谢谢

2 个答案:

答案 0 :(得分:0)

Django试图通过CSRF保护您免受insisting that you provide a CSRF Token的攻击。通常 - 如果您通过正常的POST提交表单 - 它很容易启用,您只需执行以下操作:

<form action="." method="post">{% csrf_token %}

但是因为你使用的是AJAX,所以它有点复杂。查看their recommendations的django文档或查看上一个问题dealing with the problem

基本上,您需要在使用AJAX时手动提供和提交令牌,但最佳解决方案取决于您的django版本。

答案 1 :(得分:0)

尝试使用结果$form.serialize()作为$.ajax()的数据。只要您在表单模板中的某处出现{% csrf_token %},就会选择表单中的所有值(包括令牌)并发送您的AJAX调用。