注册 登录
  • 欢迎访问"运维那点事",推荐使用Google浏览器访问,可以扫码关注本站的"微信公众号"。
  • 如果您觉得本站对你有帮助,那么可以扫码捐助以帮助本站更好地发展。

Django跨站请求伪造(CSRF)保护

Python框架 彭东稳 471次浏览 已收录 0个评论

一、概述

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

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

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

在Django中引用了CSRF防护机制,Django第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,并把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,这样就能避免被 CSRF 攻击。如果POST请求中没有token随机字符串,则返回403拒绝服务。

Django提供的CSRF防护机制:

  • 在返回的 HTTP 响应的 cookie 里,Django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token。
  • 在所有的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只需要在模板里加一个 tag, Django 就会自动帮你生成,见下面)。
  • 在处理 POST 请求之前,Django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 CSRF 攻击,返回 403 Forbidden。
  • 在所有 Ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值。

二、启用CSRF

Django中的中间件(middleware),在Django中,中间件其实就是一个类,在请求到来和结束后,Django会根据自己的规则在合适的时机执行中间件中相应的方法(请求时执行中间件的顺序是从上到下,而响应时执行中间价的顺序是从下到上)。在Django项目的settings模块中,有一个 MIDDLEWARE 变量,其中每一个元素就是一个中间件。Django默认启用CSRF中间件。

如果将此中间件去掉,此时将不会进行CSRF的校验,但如前面所述,这是一种不安全的行为。而且Django也不推荐使用。

局部使用方法:

三、表单提交POST请求

在网页template中加入csrf_token的标签就可以通过csrf校验。

在Views中大概代码逻辑如下:

四、AJAX提交POST请求

Ajax提交方式也同样需要把cookie中的csrftoken键值传到服务端。

上面html文件点击提交后,执行成功;但是往往一个程序不止一个Ajax请求,所以我们需要对每个Ajax请求都添加headers请求头,这样未免增加很多工作量;这时就需要做全局设置,不必每个都添加请求头。

<参考>

https://www.cnblogs.com/zhanghongfeng/p/7787499.html

http://www.cnblogs.com/derek1184405959/p/8445842.html


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (1)or分享 (0)
关于作者:

您必须 登录 才能发表评论!