2014-01-16 8 views
0

Прямо сейчас я настроил его так, чтобы при успешном входе в систему логин регистрации исчезает и появляется кнопка выхода. Я хочу, чтобы иметь возможность ударить logout и перейти к моей функции выхода из системы, которая просто перенаправляется на исходную страницу входа, но по какой-то причине после (только успешного) представления формы ajax внезапно я получаю 403 ошибки: Причина, указанная для отказа: CSRF токен отсутствует или неверен.no csrf token после загрузки страницы ajax

Удивление, если проблема в том, что я не передаю токен CSRF правильно. Я пробовал все, на странице https://docs.djangoproject.com/en/1.6/ref/contrib/csrf/#ajax

Вот мой код:

urls.py

from django.conf.urls import patterns, include, url 

from django.contrib import admin 
admin.autodiscover() 

urlpatterns = patterns('', 
    # Examples: 
    # url(r'^$', 'reportgenerator.views.home', name='home'), 
    # url(r'^blog/', include('blog.urls')), 

    url(r'^admin/', include(admin.site.urls)), 
    url(r'^login/', 'reportgenerator.views.login'), 
    url(r'^logout/', 'reportgenerator.views.logout'), 
) 

views.py

class LoginForm(forms.Form): 
username = forms.CharField(max_length=200) 
password = forms.CharField(max_length=200) 

def login(request): 
    c = {} 
    c.update(csrf(request)) 

    if request.POST: 
     form = LoginForm(request.POST) 
     if form.is_valid(): 
      user = auth.authenticate(username = form.cleaned_data['username'], 
       password = form.cleaned_data['password']) 
      is_success = False 
      if user is not None: 
       auth.login(request, user) 
       is_success = True 

      if request.is_ajax(): 
       if (is_success): 
        return render_to_response('login.html', c, context_instance = RequestContext(request)) 

      return render('was_failure') 
    else: 
     form = LoginForm() 

    c['form'] = form 
     return render(request, 'login.html', c) 

def logout(request): 
     auth.logout(request) 
     return HttpResponseRedirect('/login/') 

и мой JavaScript:

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

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

jQuery(function() { 
    var form1 = jQuery("#contactform"); 

    form1.submit(function(e) { 
    $.ajax({ 
     type: "POST", 
     url: form1.attr('action'), 
     data: form1.serializeArray(), 
     success: function() { 
      popup.setAttribute("style","display: none;"); 
      blurback.setAttribute("style", "-webkit-filter: blur(0px)"); 
      $("#welcome").fadeIn("slow"); 
      $("#logoutfade").fadeIn("slow"); 
     }, 
     error: function() { 
      document.getElementById("password").value = ""; 
     } 
    }); 
     e.preventDefault(); 
    }); 
}); 

ответ

0

следить за этим - Я понял пару дней спустя. Причина, по которой я столкнулся с этой проблемой, заключалась в том, что кнопка входа в систему была представлена ​​до входа в систему ajax. Когда пользователь был аутентифицирован, crsf-токен был повторно сгенерирован, а кнопка выхода на страницу имела старый токен, прикрепленный к нему, потому что он был сгенерирован ранее. Я переключил его на создание кнопки входа после вызова ajax, и все отлично поработало.

1

Dja нпо предоставляет довольно подробную информацию о том, как вы можете выполнять запросы Ajax требующие CSRF: https://docs.djangoproject.com/en/1.6/ref/contrib/csrf/

Использование JQuery без JQuery печенья аддона:

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

Использование Jquery с JQuery печенья плагин:

var csrftoken = $.cookie('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); 
     } 
    } 
}); 

EDIT (на ваш ответ) Более общий подход: Сначала убедитесь, что у вас есть промежуточное Enabled:

'django.middleware.csrf.CsrfViewMiddleware', 

Затем в файле JS:

$(document).on('click', '.some-class', function(){ 
    var $csrftoken = $.cookie('csrftoken'); 
    $.ajax({ 
     type: 'POST', 
     url: /your/url/, 
     crossDomain: false, 
     beforeSend: function(xhr) { 
      xhr.setRequestHeader("X-CSRFToken", $csrftoken); 
     }, 
     success: function(ctx) { 
      console.log(Success!) 
     } 
    }); 
}); 
+0

Эй, да, я весь день смотрю на эту документацию и пытаюсь ее реализовать, но это не помогает. Как передать это точно в моем коде? –

+0

Проверьте дополнительный код в ответе, он должен работать :) – petkostas

+0

nah Я не могу заставить его работать вообще. У меня нет никаких проблем с отправкой моей первой формы ajax, это нормально, а затем моя функция успеха работает правильно. Затем, когда я нажимаю кнопку выхода и пытаюсь перенаправить на/logout /, когда я получаю проблемы. На самом деле все работает, если я не получаю успешное возвращение, а затем у меня возникают проблемы csrf. –

Смежные вопросы