django之CSFR
django之CSFR
CSRF是什么?
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,
通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,
XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比
,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
django CSRF
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
- @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
- @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
默认django的CSRF 是开启的 在settings中
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
django 认为用户提交的数据都是不安全的,所以会利用一个认证机制来防御这种攻击的方式。
首先我们新建一个页面如下:
urlpatterns = [
path('/',views.login),
path('admin/', admin.site.urls),
url(r'^login/',views.login),
]
views中
def login(request):
if request.method=='GET':
return render(request,'lgoin.html')
elif request.method=="POST":
user=request.POST.get('user')
pwd=request.POST.get('pwd')
if user=='root' and pwd=='123':
request.session['username']=user
request.session['is_login']=True
if request.POST.get('rmb',None)=='1':
# 超时时间
request.session.set_expiry(10)
return redirect('/index/')
else:
return render(request, 'lgoin.html')
在login.html 中如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
<input type="text" name="user">
<input type="password" name="pwd">
<input type="submit" value="登陆" />
<input id="btn" type="button" value="按钮" />
</form>
</body>
</html>
提交访问一下是一个403页面
那么怎么去做一个安全的页面呢?
打开网络中。发现cookies中有 CSRFtoken 这个东西。那么这个东西是怎么来的
那么这个东西是怎么来的。首先说下原理。当get请求服务器的之后,服务器会随机发一个字符串给你,存在cookies 中。
就是为了做一个认证的方式,GET请求的时候是正常的。只有POST请求的时候发送数据服务端才会做认证
现在我们是FROM提交的。那么提交的时候一定需要是带有这个token的,才能提交成功。如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
{% csrf_token %}
<input type="text" name="user">
<input type="password" name="pwd">
<input type="checkbox" name="rmb" value="1">10秒免登陆
<input type="submit" value="登陆" />
<input id="btn" type="button" value="按钮" />
</form>
</body>
</html>
加入一个{{% csft_token %}}
再次提交一下:
看一下cookies
这边已经成功了。
那么如果发起ajax 怎么去处理呢。
HTML如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="POST">
{% csrf_token %}
<input type="text" name="user">
<input type="password" name="pwd">
<input type="checkbox" name="rmb" value="1">10秒免登陆
<input type="submit" value="登陆" />
<input id="btn" type="button" value="按钮" />
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function () {
$.ajaxSetup({
beforeSend:function (xhr,settings) {
xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
}
});
var csrftoken=$.cookie('csrftoken');
$('#btn').click(function () {
$.ajax({
url:'/login/',
type:'POST',
data:{ 'user':'root','pwd':'123' },
success:function (arg) {
}
})
})
})
</script>
</body>
</html>
点击
成功提交了ajax请求。
总结:
1. from 提交
{% csrf_token %}
2. ajax提交
$(function () {
$.ajaxSetup({
beforeSend:function (xhr,settings) {
xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
}
});
var csrftoken=$.cookie('csrftoken');
$('#btn').click(function () {
$.ajax({
url:'/login/',
type:'POST',
data:{ 'user':'root','pwd':'123' },
success:function (arg) {
}
})
})
})
csrf_protect和csrf_exempt 应用
如果说你需要单个views 不设置csrf如下:
例如index
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt
def index(request):
# 获取当前用户的随机字符串
# 根据随机字符串获取对应的信息
#
if request.session.get('is_login',None):
return render(request,'index.html',{'user':request.session['username']})
else:
return HttpResponse('<a href="/login">登陆</a>')
如果需要改成 csrf_protect








len
2019年12月17日 下午5:33
应该是form提交,你好像2个地方写成from提交了。