【问题标题】:CSRF verification failed. Request aborted in a Django formCSRF 验证失败。请求以 Django 表单中止
【发布时间】:2012-05-01 22:09:59
【问题描述】:

我正在处理图片上传表单。当用户上传图片时。在预览区域中使用 ajax 显示该图像...表单重新加载,但似乎不想显示新头像。我得到一个CSRF verification failed. Request aborted 错误。

Reason given for failure: CSRF is missing or incorrect.

我在表单中有一个 csrf_token。

模板:

<form class="nice inline-form" enctype="multipart/form-data" method="POST" action="/profile/edit/" id="avatarLoadForm">
      <input type="hidden" name="next" value="/account/settings/">
      {% csrf_token %}
      <div>
      <label for="avatar">Avatar</label>
      <div id="preview" class="frame">  
           <img src="{% if profile.user %}{% thumbnail profile.avatar 120x120 crop %}{% else %}{{ DEFAULT_AVATAR }}{% endif %}" alt="" alt="sample-pic" id="thumb" />
      </div>
      <input type="file" size="20" id="imageUpload">
      and other form info...
</form>

Ajax/Jquery:

$(document).ready(function(){

        var thumb = $('img#thumb'); 

        new AjaxUpload('imageUpload', {
            action: $('#avatarLoadForm').attr('action'),
            name: 'avatar',
            csrfmiddlewaretoken: $( "#csrfmiddlewaretoken" ).val(),

            onSubmit: function(file, extension) {
                $('#preview').addClass('loading');
            },
            onComplete: function(file, response) {
                thumb.load(function(){
                    $('#preview').removeClass('loading');
                    thumb.unbind();
                });
                thumb.attr('src', response);

            } 

        });

也许我的 Views.py 中缺少一些东西?

@login_required        
def edit_profile(request):
    context = base_context(request)
    if request.method == 'POST':
        notify = "You have successfully updated your profile."
        user_info_form = UserInfoForm(request.POST, request.FILES)
        if user_info_form.is_valid():
            if request.is_ajax():
                response = simplejson.dumps({"status": "Upload Success"})
                return HttpResponse (response, mimetype='application/json')
            messages.success(request, 'You have successfully updated your profile.')
            user_info_form.save(request.user, profile_type)
            return HttpResponseRedirect(request.POST.get('next', '/profile/' + request.user.username + '/'))
    else:
        initial = {}
        initial['first_name'] = request.user.first_name
        initial['last_name'] = request.user.last_name
        initial['email'] = request.user.email
        initial['about'] = profile.about
        initial['country'] = profile.country
        initial['about'] = profile.about
        user_info_form = UserInfoForm(initial=initial)
    context['user_info_form'] = user_info_form
    context['profile'] = profile
    return render_to_response('settings/profile.html', context, context_instance=RequestContext(request))

Settings.py:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.csrf.CsrfResponseMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'pagination.middleware.PaginationMiddleware',
)

文件上传工作没有 ajax 废话。也就是说,它实际上保存了图像,只是没有在预览中显示它。我真的不知道出了什么问题,也不知道为什么会这样。有很多关于 csrf 失败的帖子。但我找不到适合这种情况的。任何见解将不胜感激。

【问题讨论】:

    标签: jquery python ajax django


    【解决方案1】:

    是什么让您认为 csrf 令牌具有 id #csrfmiddlewaretoken?快速查看您呈现的 html 会发现模板标签不会生成 id 属性。

    改用$("input[name=csrfmiddlewaretoken]").val()

    【讨论】:

    • 感谢您指出这一点。不幸的是,它仍然返回相同的错误。我认为声明它的 type : 'POST' 可能会奏效。没用。
    • “不起作用”还不够:您的视图是否接收到带有“csrfmiddlewaretoken”和实际值的 request.POST dict?尝试 javascript 调试器或进入视图,并确保数据在那里。此外,您可以将 {{ csrf_token }} 与 csrf 中间件一起使用,将值直接注入您的 POST 函数中。
    • 你认为我能得到你的意见吗? stackoverflow.com/questions/10453221/…
    【解决方案2】:
    csrfmiddlewaretoken: $( "#csrfmiddlewaretoken" ).val(),
    

    这可能行不通。 CSRF 字段的 name/id 是动态生成的,不是这样的静态字符串。

    请参阅https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax,了解如何正确使用带有 AJAX 请求的 CSRF 中间件。

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 此链接已损坏。
      【解决方案4】:

      这对我有用:

      beforeSend: function(jqXHR, settings) {
          jqXHR.setRequestHeader('X-CSRFToken', $('input[name=csrfmiddlewaretoken]').val());
      },
      

      或者,您可以像这样从 dom 中提取 cookie,如果您的表单是通过 ajax 生成的,并且由于其呈现方式而无法发送 {{ csrf_token }},那就太好了:

      beforeSend: function(xhr, settings) {
              console.log('-------------before send--');
              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'));
              }
      } 
      

      【讨论】:

        猜你喜欢
        • 2012-12-07
        • 2015-03-08
        • 1970-01-01
        • 2014-02-03
        • 2016-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多