一,csrf攻击
- 这是我们本身的功能
1,已经实现必须登录才可以进行其他操作
登录装饰器:
def login_require(view_func):
"""实现登录装饰器"""
def wrapper(request, *args, **kwargs):
if 'login_status' in request.session and request.session['login_status']:
return view_func(request, *args, **kwargs)
else:
return redirect('/login')
return wrapper
2,实现一个修改密码的功能,用装饰器使必须登录才能进行修改密码操作
view.py
@login_require
def change_pwd(request):
if request.method == 'POST':
pwd = request.POST.get('pwd')
return HttpResponse("修改密码成功为:" + pwd)
else:
return render(request, 'llhtestapp/change_pwd.html')
change_pwd.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改密码</title>
</head>
<body>
<h3>修改密码</h3>
<form method="post" action="/change_pwd">
<p>密码:</p><input type="password" name="pwd">
<p></p><input type="submit" value="确认修改">
</form>
</body>
</html>
url配置:
url(r'^change_pwd', views.change_pwd),
3,先注销了django.middleware.csrf.CsrfViewMiddleware的中间件
4,我们现在登录成功,但是没有准备改密码(服务运行在2345端口上)
- 现在来进行csrf攻击
1,我们在另一个项目写了一个index页面
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>这是index页面</h1>
<form method="post" action="http://127.0.0.1:2345/change_pwd">
<input type="hidden" name="pwd" value="999">
<input type="submit" value="点击一下试试">
</form>
</body>
</html>
view.py
def index(request):
return render(request, 'llhtestapp02/index.html')
url配置
url(r'^index', views.index),
2,现在我们把这个服务起在另一个端口或者另一个能互通的机器上
3,在相同浏览器访问这个服务的index页
4,点击一下这个按钮
二, 如何防护
1,打开csrf防护
2,在post表单加上{% csrf_token %}
3,再试试点击
4,我们试试用本项目的服务修改密码
三,防御原理
1,渲染模板文件时在页面生成一个叫csfrmiddlewaretoken的隐藏域
2,服务器提交给浏览器保存一个名字为csfrtoken的cookie信息
3,提交表单是,两个值都会发给服务器,服务器进行比对,如果一样,则csrf验证通过,否则失效