现在我进行了设置,以便在成功登录时登录div消失并显示注销按钮。我希望能够注销注册并转到我的注销功能,只是重定向到原始登录页面,但由于某种原因(仅成功)ajax表单提交突然之后我收到403错误:失败原因:CSRF令牌丢失或不正确。
想知道问题是我没有正确传递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 :(得分:1)
Django提供了有关如何执行需要CSRF的Ajax请求的非常详细的信息: https://docs.djangoproject.com/en/1.6/ref/contrib/csrf/
使用jQuery而不使用jquery cookie addon:
// 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 cookie插件一起使用:
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);
}
}
});
编辑(给你答案) 更通用的方法: 首先确保您启用了中间件:
'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!)
}
});
});
答案 1 :(得分:0)
为了跟进这一点 - 几天后我发现了。我遇到此问题的原因是因为在ajax登录之前存在注销按钮。当用户通过身份验证时,重新生成了crsf令牌,并且该页面的注销按钮附加了旧令牌,因为它是先前生成的。在ajax调用之后,我将其切换为生成登录按钮,一切运行良好。