Django入门到放弃之CSRF_TOKEN

简介: Django入门到放弃之CSRF_TOKEN

1.django解决csrf攻击方法

django使用中间件:django.middleware.csrf.CsrfViewMiddleware解决csrf攻击

form表单使用:

1

-在form表单中 {% csrf_token%}

ajax提交

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

方式一:放到data中

    $.ajax({

           url: '/csrf_test/',

           method: 'post',

           data: {'name': $('[name="name"]').val(),

               'password': $('[name="password"]').val(),

               'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()

           },

           success: function (data) {

               console.log('成功了')

               console.log(data)

 

           },

           error: function (data) {

               console.log('xxxxx')

               console.log(data)

 

           }

       })

       方式二:放到data中

       'csrfmiddlewaretoken':'{{ csrf_token }}'

       方式三:放到头中

           headers:{'X-CSRFToken':'{{csrf_token}}'},

      

2.全局使用,局部禁csrf

1

2

3

4

5

6

7

8

9

10

11

# 全局启用,局部禁用(中间件不能注释,这个视图函数,已经没有csrf校验了)

 @csrf_exempt

 def csrf_test(request):

     if request.method=='GET':

         return render(request,'csrf_test.html')

     else:

         name=request.POST.get('name')

         password=request.POST.get('password')

         print(name)

         print(password)

         return HttpResponse('登录成功')

3.全局禁用,局部使用csrf

1

2

3

4

5

6

7

8

9

10

@csrf_protect

def csrf_test(request):

    if request.method=='GET':

        return render(request,'csrf_test.html')

    else:

        name=request.POST.get('name')

        password=request.POST.get('password')

        print(name)

        print(password)

        return HttpResponse('登录成功')

古怪的使用方式,在urls.py中

1

path('csrf_test/', csrf_exempt(views.csrf_test))

5.代码示例

登录认证中间件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

# (没有登录就可以访问:login,home,           登录后才能访问:order,userlist,logout)

 

middlewares.py

 

from django.utils.deprecation import MiddlewareMixin

from django.shortcuts import render,HttpResponse,redirect

 

class LoginAuth(MiddlewareMixin):

 

    def process_request(self, request):

        exclude_url = ['/login/']

        res = request.session.get('is_login')

        request_path = request.get_full_path()

 

        # 如果没有登录并且访问的不是login路径,则获取之前的访问路径

 

        if (not res) and (request.path not in exclude_url) :

            login_path = reverse ('login')

            return redirect('%s?returnUrl=%s'%(login_path,request_path))

 

        # 如果已经登录并且访问的是login路径,则提示注销后再登录

        elif res and (request.path in exclude_url):

            return HttpResponse('您当前已经登录,请注销后重新登录')

 

 

view.py

def login(request):

    if request.method == 'GET':

        return render(request, 'login.html')

    else:

        print('login函数')

        username = request.POST.get('username')

        password = request.POST.get('password')

 

        user_obj = models.User.objects.filter(name=username, password=password)

        if user_obj:

            request.session['is_login'= True

            path = request.GET.get('returnUrl')

            if path:

                obj = redirect(path)

            else:

                obj = redirect('login')

            return obj

        else:

            return HttpResponse('用户或密码错误')

获取前端各编码提交数据存储到request.data

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

无论前端是什么编码的请求,后端视图函数都有request.data

前端代码:

get提交 urlencoded编码

 

<div class="container-fluid">

    <div class="row">

        <div class="col-md-8 col-md-offset-2">

            <h1 class="text-center">登录界面</h1>

            <form action="" method="get">

                {% csrf_token %}

                <div class="form-group">

                    <label for="id_username">用户名:</label>

                    <input type="text" class="form-control" id="id_username" placeholder="用户名"

                           aria-describedby="basic-addon1" name="username">

                </div>

                <div class="form-group">

 

                    <label for="id_password">密码:</label>

                    <input type="password" class="form-control" id="id_password" placeholder="密码"

                           aria-describedby="basic-addon1" name="password">

                </div>

                <div class="form-group">

 

                    <input class="btn btn-danger" type="submit">

                </div>

            </form>

 

        </div>

 

    </div>

</div>

post提交 urlencoded编码  

1

除了method为post其他和get相同

post提交 form-data编码 #包含文件  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

form表单提交

<div class="container-fluid">

    <div class="row">

        <div class="col-md-8 col-md-offset-2">

            <h1 class="text-center">登录界面</h1>

            <form action="" method="post" enctype="multipart/form-data">  #注意修改编码

                {% csrf_token %}

                <div class="form-group">

                    <label for="id_username">用户名:</label>

                    <input type="text" class="form-control" id="id_username" placeholder="用户名"

                           aria-describedby="basic-addon1" name="username">

                </div>

                <div class="form-group">

 

                    <label for="id_password">密码:</label>

                    <input type="password" class="form-control" id="id_password" placeholder="密码"

                           aria-describedby="basic-addon1" name="password">

                </div>

                <div class="form-group">

                    <label for="id_file">上传文件:</label>

                    <input type="file" id="id_file" aria-describedby="basic-addon1" name="file">

                </div>

 

                <div class="form-group">

                    <input class="btn btn-danger" type="submit">

                </div>

            </form>

 

        </div>

 

    </div>

</div>

 

========================================================================

ajax提交

<div class="container-fluid">

    <div class="row">

        <div class="col-md-8 col-md-offset-2">

            <h1 class="text-center">登录界面</h1>

            <form action="" method="post" enctype="multipart/form-data">

                {% csrf_token %}

                <div class="form-group">

                    <label for="id_username">用户名:</label>

                    <input type="text" class="form-control" id="id_username" placeholder="用户名"

                           aria-describedby="basic-addon1" name="username">

                </div>

                <div class="form-group">

 

                    <label for="id_password">密码:</label>

                    <input type="password" class="form-control" id="id_password" placeholder="密码"

                           aria-describedby="basic-addon1" name="password">

                </div>

                <div class="form-group">

                    <label for="id_file">上传文件:</label>

                    <input type="file" id="id_file" aria-describedby="basic-addon1" name="file">

                </div>

 

                <div class="form-group">

                    <input class="btn btn-danger" type="submit">

                </div>

            </form>

 

        </div>

 

    </div>

</div>

 

 

<div>

    <div class="form-group">

        <label for="id_username">用户名:</label>

        <input type="text" class="form-control" id="id_username" placeholder="用户名"

               aria-describedby="basic-addon1" name="username">

    </div>

 

    <div class="form-group">

        <label for="id_password">密码:</label>

        <input type="password" class="form-control" id="id_password" placeholder="密码"

               aria-describedby="basic-addon1" name="password">

    </div>

 

    <div class="form-group">

        <label for="id_file">上传文件:</label>

        <input type="file" id="id_file" aria-describedby="basic-addon1" name="file">

    </div>

 

    <div class="form-group">

        <input class="btn btn-danger" type="button" value="提交" id="data_submit">

    </div>

 

 

    <script>

        $('#data_submit').click(function () {

            var formdata = new FormData();

            formdata.append('myfile', $("#id_file")[0].files[0]);

            formdata.append('csrfmiddlewaretoken''{{ csrf_token }}');

            formdata.append('name', $("#id_username").val());

            formdata.append('password', $("#id_password").val());

            $.ajax({

                url: {% url 'login' %},

                method: 'post',

                processData: false,

                contentType: false,

                data: formdata,

                success: function (response) {

                    console.log(response)

 

                }

            })

        })

</div>

post提交 json编码 使用ajax  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

<div class="form-group">

    <label for="id_username">用户名:</label>

    <input type="text" class="form-control" id="id_username" placeholder="用户名"

           aria-describedby="basic-addon1" name="username">

</div>

 

<div class="form-group">

    <label for="id_password">密码:</label>

    <input type="password" class="form-control" id="id_password" placeholder="密码"

           aria-describedby="basic-addon1" name="password">

</div>

 

<div class="form-group">

    <input class="btn btn-danger" type="button" value="提交" id="data_submit">

</div>

 

        <script>

                    $('#data_submit').click(function () {

                $.ajax({

                    url: {% url 'login' %},

                    method: 'post',

                    contentType: 'application/json',

                    headers:{'X-CSRFToken':'{{csrf_token}}'},

                    data:JSON.stringify({name:$("#id_username").val(),password:$("#id_password").val()}),

 

                    success: function (response) {

                        console.log(response)

                    }

                })

 

             });

 

        </script>

中间件代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

class Data_Conv(MiddlewareMixin):

 

    def process_request(self, request):

        request.data = {}

        # get提交数据,urlencoded编码方式,把form数据转换成一个字串(name1=value1&name2=value2…)

        if request.method == 'GET' and request.META.get('CONTENT_TYPE'== 'application/x-www-form-urlencoded':

            for in request.GET:

               request.data[k]=request.GET[k]

 

        # post提交数据,urlencoded编码方式,把form数据封装到http body中

        elif request.method == 'POST' and request.META.get('CONTENT_TYPE'== 'application/x-www-form-urlencoded':

            for in request.POST:

                request.data[k] = request.POST[k]

 

        # post提交数据,form-data编码方式,把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),

        # Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary).

        # 需要注意的是POST中只有文件的名称,文件的数据实际保存在request.FILES中,通过  request.FILES.get('myfile').chunks()获取文件的数据

        elif request.method == 'POST' and request.META.get('CONTENT_TYPE'== 'multipart/form-data':

            for in request.POST:

                request.data[k] = request.POST[k]

 

        # post提交数据,json编码方式, ajax请求中 content-type:application/json,在后台接受前台提交的数据,前端提交的数据是 json格式的字符串

        elif request.method == 'POST' and request.META.get('CONTENT_TYPE'== 'application/json':

            post_data = json.loads(request.body)

            for in post_data:

                request.data[k] = post_data[k]

实现频率限制的功能(同一个ip地址,一分钟只能访问5次)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

class OverTime(MiddlewareMixin):

    def process_request(self, request):

        # 获取客户端IP地址

        IP = request.META.get('REMOTE_ADDR')

        print(IP)

        # 获取该IP地址的值,如果没有,给一个默认列表[]

        lis = request.session.get(IP, [])

        # 获取当前时间

        curr_time = time.time()

        # 判断操作次数是否小于3次

        if len(lis) < 3:

            # 如果小于3次,添加本次操作时间

            lis.append(curr_time)

            # 保存

            request.session[IP] = lis

        else:

            # 如果本次操作时间减去第一次操作时间小于60秒,则不让其继续操作

            if time.time() - lis[0] < 60:

                return HttpResponse('操作过于频繁')

            else:

                # 如果大于60秒则交叉复制

                lis[0], lis[1], lis[2= lis[1], lis[2], time.time()

                # 保存

                request.session[IP] = lis


相关文章
|
5天前
|
Java API 数据库
Django:从入门到精通
【11月更文挑战第18天】Django是一个由Python编写的高级Web应用框架,以其简洁性、安全性和高效性而闻名。Django最初由Adrian Holovaty和Simon Willison于2003年开发,旨在简化Web应用的开发过程。作为一个开放源代码项目,Django迅速吸引了大量的开发者和用户,成为了Python Web开发领域的重要工具之一。
13 1
|
1月前
|
存储 Shell 数据库
Python编程--Django入门:用户账户(二)
Python编程--Django入门:用户账户(二)
|
1月前
|
存储 数据库 Python
Python编程--Django入门:用户账户(一)
Python编程--Django入门:用户账户(一)
|
2月前
|
SQL 安全 数据库
从入门到精通:Python Web安全守护指南,SQL注入、XSS、CSRF全防御!
【9月更文挑战第13天】在开发Python Web应用时,安全性至关重要。本文通过问答形式,详细介绍如何防范SQL注入、XSS及CSRF等常见威胁。通过使用参数化查询、HTML转义和CSRF令牌等技术,确保应用安全。附带示例代码,帮助读者从入门到精通Python Web安全。
86 6
|
3月前
|
前端开发 关系型数据库 Python
Django入门到放弃之分页器
Django入门到放弃之分页器
|
3月前
|
数据库 开发者 Java
颠覆传统开发:Hibernate与Spring Boot的集成,让你的开发效率飞跃式提升!
【8月更文挑战第31天】在 Java 开发中,Spring Boot 和 Hibernate 已成为许多开发者的首选技术栈。Spring Boot 简化了配置和部署过程,而 Hibernate 则是一个强大的 ORM 框架,用于管理数据库交互。将两者结合使用,可以极大提升开发效率并构建高性能的现代 Java 应用。本文将通过代码示例展示如何在 Spring Boot 项目中集成 Hibernate,并实现基本的数据库操作,包括添加依赖、配置数据源、创建实体类和仓库接口,以及在服务层和控制器中处理 HTTP 请求。这种组合不仅简化了配置,还提供了一套强大的工具来快速开发现代 Java 应用程序。
194 0
|
3月前
|
开发框架 安全 数据库
解锁Django框架神秘面纱!从入门到实战,掌握这些技巧,让你的Web应用秒变高效神器!
【8月更文挑战第31天】Django 是 Python 的明星 Web 开发框架,以其高效、安全及可扩展性著称,适用于构建各类 Web 应用。本文从 Django 基础概念出发,介绍其 MTV 架构,涵盖模型(Model)、模板(Template)、视图(View)等核心组件,并通过示例代码展示实际应用。此外,还将探讨路由配置、管理界面及实战技巧,帮助读者全面掌握 Django,为高效 Web 开发打下坚实基础。
53 0
|
3月前
|
关系型数据库 MySQL 机器人
Django入门到放弃之数据库配置
Django入门到放弃之数据库配置
|
3月前
|
缓存 中间件 数据库
Django入门到放弃之缓存及信号机制
Django入门到放弃之缓存及信号机制
|
3月前
|
前端开发 数据库 数据安全/隐私保护
Django入门到放弃之Auth模块
Django入门到放弃之Auth模块