页面包含两个表单,一个用于身份验证,另一个用于提问。通过AJAX调用提交auth表单并成功登录用户。但是,如果用户在登录后提交问题表单,则会抛出“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函数。对这种行为都没有任何影响。
答案 0 :(得分:0)
当我遇到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 i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
您也可以使用装饰器禁用csrf @csrf_excempt 但这是另一种方法