繁体   English   中英

在ajax登录后提交其他表单时,CSRF令牌错误

[英]CSRF token error when submitting different form after ajax login

页面包含两种形式,一种用于身份验证,另一种用于提问。 身份验证表单是通过AJAX调用提交的,并已成功登录用户。 但是,如果用户在登录后提交问题表单,则会抛出“ CSRF令牌丢失或不正确”。

main.js

$(function() {
    // Submit post on submit
    $('#login-form').on('submit', function(event){
        event.preventDefault();
        console.log("form submitted!")
        create_post();
    });

    // AJAX for auth
    function create_post() {
        $.ajax({
            url : "perfil/entrar/", // the endpoint
            type : "POST", // http method
            data : { username : $('#username-text').val(), password : $('#password-text').val() }, // data sent with the post request
            // handle a successful response
            success : function(json) {
                $('#username-text').val(''); // remove the value from the input
                $('#password-text').val(''); // remove the value from the input
            },
            // handle a non-successful response
            error : function(xhr,errmsg,err) {
                console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
            }
        });
    };


    // This function gets cookie with a given name
    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');

    /*
    The functions below will create a header with csrftoken
    */

    function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    function sameOrigin(url) {
        // test that a given url is a same-origin URL
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }

    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
                // Send the token to same-origin, relative URLs only.
                // Send the token only if the method warrants CSRF protection
                // Using the CSRFToken value acquired earlier
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });
    // Open modal dialog for authentification
    $('#myModal').on('shown.bs.modal', function () {
      $('#myInput').focus()
    });

});

的index.html

            <form method="post" id=class="form-horizontal" action="/perguntar/">
                {% csrf_token %}
                        <div class="col-md-7">
                        {{ questionform.title }}
                        {{ questionform.title.errors }}
                        {{ questionform.body }}
                        {{ questionform.body.errors }}
                        </div>
                        <div class="form-group">
                            <div class="col-sm-4">
                                <div class="input-group">
                                    <div class="input-group-addon">$</div>
                                    <div>{{ questionform.orcamento }}</div>
                                    {{ questionform.orcamento.errors }}
                                    <div class="input-group-addon">,00</div>
                                </div>
                                {{ questionform.category }}
                                {{ questionform.category.errors }}
                                <button type="submit" class="btn btn-primary btn-block">Perguntar</button>
                            </div>
                        </div>
            </form>

                        <form method="POST" id="login-form">
                          {% csrf_token %}
                        <label for="username-text">Usuario:</label>
                        <input type="text" name="username" value="" id="username-text">
                        <label for="password-text">Senha:</label>
                        <input type="password" name="password" value="" id="password-text">
                        <input type="submit" value="login" />
                        <input type="hidden" name="next" value="{{ next|escape }}" />
                       </form>

login_view

def login_view(request):
    if request.method == 'POST':
        response_data = {}
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = auth.authenticate(username=username, password=password)
        if user is not None and user.is_active:
            auth.login(request, user)
            response_data['result'] = 'success'
            return HttpResponse(
                        json.dumps(response_data),
                        content_type="application/json"
            )
        else:
            return render(request, 'error.html', {
        })
    else:
        return render(request, 'login.html', {
        })

askQuestion_view

def perguntar(request):
    if request.method == 'POST':
        form = ModelThreadForm(request.POST)
        if form.is_valid():
            thread = form.save(commit=False)
            if request.user.is_authenticated():
                thread.published = True
                thread.creator = request.user
                thread.save()
            else:
                thread.published = False
                thread.creator = None
                thread.save()
        return HttpResponseRedirect(thread.get_absolute_url())
    else:
        form = ModelThreadForm()
    return render(request, 'perguntar.html', {
                               'questionform': form,
    })

我试过使用

    data : { 'csrftoken': '{{ csrf_token }}', username : $('#username-text').val(), password : $('#password-text').val() }, // data sent with the post request

代替

        data : { 'X-CSRFToken': '{{ csrf_token }}', username : $('#username-text').val(), password : $('#password-text').val() }, // data sent with the post request

并消除了main.js上的sameOrigin函数。 两者都没有对行为产生任何影响。

当我遇到CSRF问题时,这对我有所帮助

http://chevalry.livejournal.com/206466.html

 $.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 ie locally. xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); } } }); 

您也可以使用装饰器@csrf_excempt禁用csrf,但这是另一种方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM