1. 什么是CSRF攻击?
CSRF(Cross-site request forgery),中文名“跨站请求伪造”。它是一种针对Web应用程序的攻击方式,攻击者利用用户已登录的身份,在用户不知情的情况下进行非法操作,比如删除一篇文章、转账等。在Django中,CSRF攻击是需要预防的。
1.1 CSRF攻击的原理:
攻击者在不让用户察觉的情况下,将一个HTTP请求发送给web服务器,通常会伪装成用户自己发出的请求。由于请求中包含了用户的session信息,所以web服务器会认为这个请求是用户自己发出的。
1.2 示例:
假设某个合法的网站中有一个表单,用户需要在该表单中输入一些内容后点击提交来完成相应的操作。该表单的提交方法为POST方式,而提交给服务器的URL地址在显示表单的HTML代码中。那么,我们便可以思考一下下面两种情况:
情况一:用户访问该网站后,输入相应内容后提交表单。此时,提交表单的URL地址以及用户的session信息都已经存储在该用户的浏览器cookies中,服务器收到请求后处理相应信息并返回给用户正确的结果。
情况二:攻击者事先向用户的电子邮箱发送一封包含恶意代码的电子邮件。在用户打开该邮件后,恶意代码将向目标网站发送一条请求,以此来实现CSRF攻击的目的。由于恶意代码中已经设置好了提交表单所需要的所有参数,所以用户并不会察觉自己提交了表单。此时,服务器会认为该请求是合法的,并以同样的方式进行处理,从而导致不好的后果。
2. Django中预防CSRF攻击的操作
Django为了防止CSRF攻击,提供了以下三种方式:
2.1 csrf_token标签
Django提供了一个csrf_token标签,可以用于在表单中生成一个隐藏的字段,这个字段用于存放由Django生成的、跨站点请求时所需的一个随机令牌(token)。每次向服务器发送请求的时候,都要将这个令牌带上。在Django中,可以使用csrf_exempt装饰器来取消某个视图函数的csrf验证。
#视图函数中取消csrf验证
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def some_view(request):
#some code
pass
2.2 CsrfViewMiddleware中间件
Django还内置了CsrfViewMiddleware中间件,这个中间件会在用户访问每一个页面的时候都自动检查csrf_token是否合法。如果不合法,则会向用户返回HTTP/1.1 403 Forbidden响应。
#中间件开启示例(settings中)
MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware',
#....
]
2.3 AJAX请求中的csrf_token
对于使用AJAX技术需要发送POST请求的场景,因为Django从1.2版本起使用了CSRF保护,所以需要在HTTP头部携带csrf_token才能通过Django的CSRF验证。其实,AJAX技术已经不是什么新奇的技术了,JSON格式的数据也已经成为AJAX传输数据的标准,而且方便易用。所以,在进行AJAX请求的时候,可以在POST请求的数据中加上csrfmiddlewaretoken字段,同时将csrf_token作为该字段的值。
$.ajax({
type: "POST",
//数据格式是JSON字符串
contentType: "application/json",
url: "/test",
headers: {
'X-CSRFToken': getCookie('csrftoken')
},
data: JSON.stringify({"name": "tony", "age": 18, "csrfmiddlewaretoken": "{{ csrf_token }}" }),
dataType: "json",
success: function (data) {
alert(data);
},
error: function (error) {
alert(error.responseText);
}
});
3. 总结
对于CSRF攻击,我们可以采用的措施有很多,比如form_token,偏爱Cookie等等。而在Django中采用了csrf_token标签、CsrfViewMiddleware中间件和在AJAX请求中携带csrf_token等方式,保护程序在运行过程中不会受到CSRF攻击。因此,在进行Django开发时,一定要注意加上这些安全措施,以免自己的程序被攻击,造成不好的影响。