1.CSRF介绍
csrf,跨站请求伪造,也被称为"One Click Attack"或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
为了防止这种现象,需要在Ajax提交时,为form表单添加一个随机字符串,以避免被恶意篡改。Django中为了实现这一功能,可以通过在settings文件中,使用以下中间件:
django.middleware.csrf.CsrfViewMiddleware
以上方法是在全局设置,在局部设置时:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect:装饰某个函数,为该函数强制设置防跨站请求伪造功能,即便在settings文件中没有设置全局中间件。
@csrf_exempt:装饰某个函数,取消该函数防跨站请求伪造功能,即便在settings文件中设置了全局中间件。
2.使用例子
在views.py文件中写如下:
@csrf_protect
def login(request):
from django.conf import settings
print(settings.CSRF_HEADER_NAME) #HTTP_X_CSRFTOKEN
#X-CSRFtoken 实际
if request.method=="GET":
return render(request,"c_login.html")
elif request.method=="POST":
u=request.POST.get("username")
pwd=request.POST.get("pwd")
print(u,pwd)
if u in user_info and pwd==user_info[u]["pwd"]:
request.session["username"]=u
request.session["is_login"]=True
if request.POST.get("no_login",None)=="1": #状态在前端被选中
request.session.set_expiry(10) #人为设置超时时间为10秒钟
print("10秒后,超时")
return redirect('/cook/s_index/')
else:
return render(request,"c_login.html")
在c_login文件中写如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<div>
<form action="/cook/login/" method="post">
<input type="text" name="username" placeholder="用户名">
{% csrf_token %}
<input type="password" style="display: none;" >
<input type="password" name="pwd" placeholder="密码" autocomplete="new_password" >
<input type="checkbox" name="no_login" value="1"/>10秒内免登录
<input type="submit" value="提交" id="btn2">
<input type="button" value="测试提交" id="btn1">
</form>
</div>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script type="text/javascript">
$(function(){
$.ajaxSetup({
beforeSend:function(xhr,settings){
{#xhr 是xmlhttpRequest对象 xhr.open() xhr.send() 在发送前统一做配置#}
xhr.setRequestHeader("X-CSRFtoken",$.cookie('csrftoken'));
}
});
$('#btn1').click(function () {
$.ajax({
url:'/cook/login',
method:'GET',
data:{"username":'A','pwd':'123456'},
{#headers:{"x-CSRFtoken":$.cookie('csrftoken')},#}
success:function (arg) {
}
})
})
})
</script>
</body>
</html>
为了实现某些附加功能,如请求方式为get、head、option、trace的ajax请求不做CSRF验证,代码如下:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
{% csrf_token %}
<input type="button" onclick="Do();" value="Do it"/>
<script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
<script src="/static/plugin/jquery/jquery.cookie.js"></script>
<script type="text/javascript">
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
function Do(){
$.ajax({
url:"/app01/test/",
data:{id:1},
type:'POST',
success:function(data){
console.log(data);
}
});
}
</script>
</body>
</html>