csrf 跨站请求伪造

时间:2023-02-09 17:59:00

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware来完成。

 

 第1次来访问的时候(get方法),先拿到字符串;下次再来访问的时候(post方法)也必须带着这一串字符串才能成功。

CSRF是指提交数据的时候必须通过验证。

cookie和session是关于用户名/密码保存的。

 

CSRF字符串不仅在表单里面有了,在cookie里面也有了。

当用form表单提交的时候,把随机字符串和cookie值都发过去了。

 

 

如果用Ajax往后台发数据的时候,只需要把cookie值拿到,放到请求头里面发过去就可以了。

加cookie值的Ajax请求过程:

带上随机字符串的话, 才能登录成功。从cookie里面先把随机字符串获取到。获取方法如下:$.cookie('csrftoken'),具体方法如代码所示

csrf 跨站请求伪造csrf 跨站请求伪造
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <form action="/login/" method="post">
 9     {% csrf_token %}
10     <input type="text" name="user" placeholder="user"/>
11     <input type="password" name="pwd" placeholder="pwd"/>
12     <input type="checkbox" name="rmb" value="2">10秒免登陆
13     <input type="submit" value="提交"/>
14     <input type="button" id="but1" value="按钮"/>
15     <input type="button" id="but2" value="按钮"/>
16 </form>
17 <script src="/static/jquery-1.12.4.js"></script>
18 <script src="/static/jquery.cookie.js"></script>
19 <script>
20     $(function () {
21         $.ajaxSetup({
22             beforeSend: function (xhr, settings) {
23                 xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'))
24             }
25         });
26 
27         $('#but1').click(function () {
28             $.ajax({
29                 url: '/login/',
30                 type: 'POST',
31                 data: {'user': 'root', 'pwd': '123'},
32                 success: function (arg) {
33                 }
34             })
35         })
36     })
37 </script>
38 </body>
39 </html>
View Code

不加没有加cookie值的Ajax请求过程:报错通不过CSRF验证,报403错误

 但是后台需要通过key去获取这个值,那么这个值对应的key是什么呢?通过打印settings.CSRF_HEADER_NAME可知,

key是HTTP_X_CSRFTOKEN, HTTP_ 是django自动给加上的,所以我们发送的时候,只需要把key设置成 X_CSRFTOKEN就可以了。 

由于请求头里面不能出现下划线,所以最终设置的时候应该写成 X-CSRFTOKEN。

 

理论上我们把请求头设置成X_CSRFTOKEN 就可以了。

但是由于Django有要求,请求头里面不能出现下划线,所以最终我们把请求头设置成X-CSRFTOKEN 的样子。

按照官网推荐,建议写成

X-CSRFtoken。

1 headers:{'X-CSRFtoken':$.cookie('csrftoken')},

Form表单提交与Ajax方法提交的不同之处在于,去不同的地方拿csrf_token

 在 Ajax中写headers太麻烦了,可以用setup 对整个页面中所有的Ajax操作做一个配置。

表示在发送ajax之前,会先执行一下那个函数。

xhr是XMLHttpRequest 对象,所有的ajax操作底层用的都是它。

 

而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

csrf 跨站请求伪造

  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

csrf 跨站请求伪造

 

 csrf 跨站请求伪造

 

csrf 跨站请求伪造

1.中间件,在其它程序中,有的叫管道,有的叫http handler。下面是原生的中间件

写中间件,新建文件夹Middle,新建m1.py

在setting里注册中间件,1个类就是1个中间件

做测试,看是否所有的请求过来时,都必须一一经过中间件。(写了一个test函数)

 

当想拿返回值的时候,可以通过response函数。request里面存放的是客户端的所有数据,可以有request.GET,request.POST,request.method等方法。

通过第一个中间件的时候,就可以判断一下,是否携带了请求头(CSRFtoken),如果没有带请求头的话,在第1步就可以终止了。

完善我们自己写的中间件。其实中间件就是一个普通的类。

 

整个请求的流程如下:1.10版本,到哪个中间件发生了阻断,就从哪个中间件返回。

 

注意process_request, process_response 2个函数名是写死的,不能变。

解析process_view函数的意义

def process_view(self,request,view_func,view_func_args,view_func_kwargs):
view_func:指的就是URL中对应的那个函数,在这里指test函数
view_func_args:对应test函数中接收的参数,对应的URL如下:url(r'^test/(\d+)$', views.test), def test(request,nid)
view_func_kwargs:对应test函数中接收的字典,对应的URL如下:url(r'^test/(?P<nid>\d+)$', views.test), def test(request,nid)

def process_exception(self,request,exception): 这个函数一般情况下不执行,只有在出错时才执行。指的是异常信息

def process_template_response (self,request,response):  默认情况下也不执行,

如果views中的函数返回的对象中,具有render方法,那这个函数就会执行了。

 

process_Request, 发出请求

process_view, 通过以后,就会达到view函数

process_response, 开始返回。