除了使用django内置表单,有时往往我们需要自定义表单。对于自定义表单post方式提交往往会带来由csrf(跨站请求伪造)产生的错误”csrf verification failed. request aborted.”
本篇文章主要针对”表单提交”和”ajax提交”两种方式来解决csrf带来的错误
一、表单提交
template:
计算数字和
{% csrf_token %}
views.py:
def calculate(request):
if request.post:
a=request.post[“valuea”]
b=request.post[“valueb”]
c=str(int(a)+int(b))
return render_to_response(‘result.html’,{‘result’:c})
else:
return render_to_response(‘calculation.html’,context_instance=requestcontext(request))
需要注意:
(1)在标签内添加{% csrf_token %},这样在表单提交的过程中,会产生”csrfmiddlewaretoken”标识去防止csrf
(2)在get请求页面时,需要添加context_instance=requestcontext(request) ,它和{% csrf_token %}配合使用,缺少一个都会出现上述错误,requestcontext 需要在 django.shortcuts 导入
(3)只有当表单以post方式提交时,才需要验证csrf,get方式是不需要的
二、ajax提交
同比与表单提交,ajax提交需要进行额外的操作,ajax提交时需要自己提供”csrfmiddlewaretoken”标识参数。我们除了需要引入jquery外还需要引入一段js代码
jquery(document).ajaxsend(function(event, 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;
}
function sameorigin(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));
}
function safemethod(method) {
return (/^(get|head|options|trace)$/.test(method));
}
if (!safemethod(settings.type) && sameorigin(settings.url)) {
xhr.setrequestheader("x-csrftoken", getcookie('csrftoken'));
}
});
template:
ajax 提交
《script》
jquery(document).ajaxsend(function(event, 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;
}
function sameorigin(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));
}
function safemethod(method) {
return (/^(get|head|options|trace)$/.test(method));
}
if (!safemethod(settings.type) && sameorigin(settings.url)) {
xhr.setrequestheader("x-csrftoken", getcookie('csrftoken'));
}
});
《script》
$(function(){
$.ajaxsetup({
data:{csrfmiddlewaretoken: '{{ csrf_token }}'}
});
$("#comment").click(function(){
$.post('{% url 'ajaxrequest' %}',{"a":$("#a").val(),"b":$("#b").val()},function(data){
$("#result").html(data);
});
});
});
《script》
计算的结果为:
view.py:
def ajaxrequest(request):
if request.post:
a =request.post[“a”]
b=request.post[“b”]
c=int(a)+int(b)
return jsonresponse(c,safe=false)
else:
return render_to_response(‘ajaxdemo.html’,context_instance=requestcontext(request))
需要注意:
(1)在使用引入的js代码后,需要添加如下代码,这样js就可以自动帮我们生成”csrfmiddlewaretoken”标识,接下来你就可以使用$.post()了
$.ajaxsetup({
data:{csrfmiddlewaretoken: ‘{{ csrf_token }}’}
});
(2)context_instance=requestcontext(request) 并不是必须的
(3)get请求不需要以上操作,直接使用$.get()即可
注:本文使用的django1.8.3版本进行测试。
以上就是本文的全部内容,希望对大家的学习有所帮助。