CSRF验证失败。请求以Django形式中止

时间:2021-08-08 20:34:24

I'm working on a image upload form. When the user uploads an image. Display that image with ajax in the preview area... The form reloads but it seems like it doesn't want to show the new avatar. And I get a CSRF verification failed. Request aborted error.

我正在制作一个图像上传表单。当用户上传图片时。在预览区使用ajax显示该图像……表单重新加载,但它似乎不想显示新的头像。我的CSRF验证失败了。请求中止错误。

Reason given for failure: CSRF is missing or incorrect.

失败原因:CSRF丢失或不正确。

I have a csrf_token in place within the form.

我在表单中有一个csrf_token。

Template:

模板:

<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:

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);

            } 

        });

Maybe there's something I'm missing in my 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:

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',
)

The file upload works without the ajax crap. As to say, it actually saves the image, just doesn't show it in the preview. I really don't know what's wrong or why this is happening. There's been alot of posts regarding csrf failures. But I can't find one that pertains to this situation. Any insight would be very much appreciated.

文件上传工作没有ajax垃圾。也就是说,它实际上保存了图像,只是没有在预览中显示出来。我真的不知道这是怎么回事,也不知道为什么。关于csrf故障有很多帖子。但是我找不到一个和这种情况有关的。任何见解都将非常感谢。

4 个解决方案

#1


3  

What makes you think the csrf token has an id #csrfmiddlewaretoken? A quick look at your rendered html would reveal the template tag does not generate an id attribute.

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

Try $("input[name=csrfmiddlewaretoken]").val() instead

试着$(“输入[name = csrfmiddlewaretoken]”).val()

#2


0  

csrfmiddlewaretoken: $( "#csrfmiddlewaretoken" ).val(),

This probably won't work. The name/id of the CSRF field is generated dynamically and isn't a static string like this.

这可能不会工作。CSRF字段的名称/id是动态生成的,不是这样的静态字符串。

See https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax for how to properly use the CSRF middleware with AJAX requests.

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

#3


0  

see this http://djangolinks.com/detail/ajax-post-requests-csrf-fix-69/

看到这个http://djangolinks.com/detail/ajax-post-requests-csrf-fix-69/

#4


0  

This works for me:

这工作对我来说:

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

Alternatively, you could extract the cookie out of the dom like so which is great if your form is generated via ajax and can not send the {{ csrf_token }} due to the way it renders:

或者,您也可以像这样从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'));
        }
} 

#1


3  

What makes you think the csrf token has an id #csrfmiddlewaretoken? A quick look at your rendered html would reveal the template tag does not generate an id attribute.

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

Try $("input[name=csrfmiddlewaretoken]").val() instead

试着$(“输入[name = csrfmiddlewaretoken]”).val()

#2


0  

csrfmiddlewaretoken: $( "#csrfmiddlewaretoken" ).val(),

This probably won't work. The name/id of the CSRF field is generated dynamically and isn't a static string like this.

这可能不会工作。CSRF字段的名称/id是动态生成的,不是这样的静态字符串。

See https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax for how to properly use the CSRF middleware with AJAX requests.

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

#3


0  

see this http://djangolinks.com/detail/ajax-post-requests-csrf-fix-69/

看到这个http://djangolinks.com/detail/ajax-post-requests-csrf-fix-69/

#4


0  

This works for me:

这工作对我来说:

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

Alternatively, you could extract the cookie out of the dom like so which is great if your form is generated via ajax and can not send the {{ csrf_token }} due to the way it renders:

或者,您也可以像这样从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'));
        }
}