18_CSRF_TOKEN跨站请求伪造
2018-11-23 本文已影响0人
knot98
CSRF_TOKEN跨站请求伪造
一、CSRF是什么
-
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
攻击者盗用了你的身份,以你的名义发送恶意请求,但对服务器来说这个请求是完全合法的
二、CSRF攻击原理
如下图:

从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)
3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
三、CSRF攻击防范
目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证
四、CSRF的简单使用
方法一:在form表单中应用:
<form action="" method="post">
{% csrf_token %}
<p>用户名:<input type="text" name="name"></p>
<p>密码:<input type="text" name="password"></p>
<p><input type="submit"></p>
</form>
方法二:在AJAX中
放在data里:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="/static/jquery-3.3.1.js"></script>
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>用户名:<input type="text" name="name"></p>
<p>密码:<input type="text" name="password" id="pwd"></p>
<p><input type="submit"></p>
</form>
<button class="btn">点我</button>
</body>
<script>
$(".btn").click(function () {
$.ajax({
url: '',
type: 'post',
data: {
'name': $('[name="name"]').val(),
'password': $("#pwd").val(),
'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
},
success: function (data) {
console.log(data)
}
})
})
</script>
</html>
放在cookie里:
- 获取cookie:document.cookie
- 是一个字符串,可以自己用js切割,也可以用jquery的插件
- 获取cookie:$.cookie('csrftoken')
- 设置cookie:$.cookie('key','value')
五、CSRF的全站禁用、局部使用以及局部禁用
全站禁用:在settings.py文件中注释掉中间件中的:
'django.middleware.csrf.CsrfViewMiddleware',
局部禁用:用装饰器(在FBV中使用)
from django.views.decorators.csrf import csrf_exempt,csrf_protect
# 不再检测,局部禁用(前提是全站使用)
# @csrf_exempt
# 检测,局部使用(前提是全站禁用)
# @csrf_protect
def csrf_token(request):
if request.method=='POST':
print(request.POST)
return HttpResponse('ok')
return render(request,'csrf_token.html')
在CBV中使用:
# 需要导入特定的装饰器装饰一下,局部禁用、局部使用的装饰器
from django.views import View
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
# CBV的csrf装饰器,只能加载类上(指定方法为dispatch)和dispatch方法上
@method_decorator(csrf_exempt,name='dispatch')
class Foo(View):
# @method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(HomeView, self).dispatch(request, *args, **kwargs)
def get(self,request):
pass
def post(self,request):
pass