Django之CSRF

网页向后端传送数据的时候有两种方式,get和post。通过设置form中的method来达到是否采用get或者是post

<form action="/show_all/" method="POST">
但是django中使用post的话会遇到如下的错误

这个错误的意思是csrf校验失败,request请求被丢弃掉。我们先来了解下什么是csrf。

CSRF, Cross Site Request Forgery, 跨站点伪造请求。举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到你的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造

举个例子:

假如用户abc登录了银行的网站,并且向abc2进行了转账,对银行发送的请求是 http://bank.example/withdraw?account=abc&amount=1000000&for=abc2. 通常情况下,请求发送到服务器后,服务器会首先验证是否是合法的session,如果是则转账成功。假设黑客也有同样银行的账号。他知道转账的时候会生成如上的请求链接。黑客也可以发送同样的请求给服务器要求转账给自己。但是服务器校验他的这个请求不是合法的session。因此黑客想到了CSRF的方式。他自己做一个网站,在网站中发下如下链接:http://bank.example/withdraw?account=abc&amount=1000000&for=heike 并且通过广告或其他的方式诱使abc点击这个链接,上述 url 就会从 abc的浏览器发向银行,而这个请求会附带 abc浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 abc 的认证信息。但是,如果 abc 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 abc 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 abc 的账号转移到黑客的账号,而 abc 当时毫不知情

那么解决办法是什么呢:

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

那么回到django中的post失败有两种解决办法:

解决办法一:将csrf中间层注释掉

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',
]
此时将不会进行csrf的校验,但如前面所述,这是一种不安全的行为。而且djano也不推荐使用
 
解决办法二:
在前面的提示中有这样一句话:

In any template that uses a POST form, use the csrf_token tag inside the <form> element if the form is for an internal URL, e.g.:

<form action="" method="post">{% csrf_token %}

也就是说在网页中加入csrf_token的标签就可以通过csrf校验
Django 提供的 CSRF 防护机制:
1 django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,这样就能避免被 CSRF 攻击。
2 在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token,在所有的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只需要在模板里加一个 tag, django 就会自动帮你生成,见下面)
3 在处理 POST 请求之前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden.
4 在所有 ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值

posted @ 2017-11-05 15:18  red_leaf_412  阅读(6179)  评论(1编辑  收藏  举报