zoukankan      html  css  js  c++  java
  • django框架

    今日内容:

    1.django中间件

    2.csrf跨站请求伪造

    3.auth模块

    4.settings功能插拔式源码

    django流程图(重点)

    1.django中间件

    django中间件就类似于是django的保安,请求的时候需要先经过中间件才能到达django后端
    (urls,views,templates,models),响应走的时候也需要经过中间件才能到达web服务网关接口。

    django有他自己默认的七个中间件:

                django默认的七个中间件
                    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',
                                ]
                    

    那么django中间件是用来干什么的(重要)

    1.网站全局的校验,访问频率限制,权限校验,只要是涉及到全局的校验你都可以在中间件中完成
    2.django的中间件是所有web框架中,做的最好的一个。

    django中间件中有五个用户可以自定义的方法:

    需要掌握的
    1.process_request()方法
    2.process_response()方法
    需要了解的方法
    3.process_view()
    4.process_exception()
    5.process_template_response()

    接下来就介绍这5个方法:

    1.process_request()方法

    它的执行规律:
        1.请求来的时候,会经过每一个中间件里面的process_request(从上往下依次执行),
        2.如果方法里面直接返回了HttpResponse对象,那么会直接返回,不在往下执行,
       基于该特点就可以做限制访问频率限制,身份校验,权限校验。

    注意:
    代码:
    创建一个mymiddleware文件夹
     1 from django.utils.deprecation import MiddlewareMixin
     2 from django.shortcuts import HttpResponse
     3 
     4 class MyMdd(MiddlewareMixin):
     5     def process_request(self,request):
     6         print('我是第一个中间件里面的process_request方法')
     7         # return HttpResponse('123')
     8 
     9 class MyMdd1(MiddlewareMixin):
    10     def process_request(self,request):
    11         print('我是第二个中间件里面的process_request方法')
    View Code

    views里面:

    1 def index(request):
    2     print('我是index视图函数')
    3     return HttpResponse('index')
    View Code

    2.process_response()方法

    执行规律:
        1.必须将response形参返回,因为这个形参指代的就是要返回给前端的数据
        2.响应走的时候,会依次经过每一个中间件里面的process_response方法(执行顺序从下往上)

    代码:
     1 from django.utils.deprecation import MiddlewareMixin
     2 from django.shortcuts import HttpResponse
     3 
     4 class MyMdd(MiddlewareMixin):
     5     def process_request(self,request):
     6         print('我是第一个中间件里面的process_request方法')
     7         # return HttpResponse('123')
     8 
     9     def process_response(self,request,response):
    10         print('我是第一个中间件里面的process_response方法')
    11         return response
    12 
    13 
    14 
    15 class MyMdd1(MiddlewareMixin):
    16     def process_request(self,request):
    17         print('我是第二个中间件里面的process_request方法')
    18 
    19     def process_response(self,request,response):
    20         print('我是第二个中间件里面的process_response方法')
    21         return response
    View Code

    需要了解的方法:

    需要了解的方法
    要了解的方法
                            3.process_view()
                                1.在路由匹配成功执行视图函数之前 触发
                                
                            4.process_exception()
                                1.当你的视图函数报错时  就会自动执行
                                
                            5.process_template_response()
                                1.当你返回的HttpResponse对象中必须包含render属性才会触发
                                def index(request):
                                    print('我是index视图函数')
                                    def render():
                                        return HttpResponse('什么鬼玩意')
                                    obj = HttpResponse('index')
                                    obj.render = render
                                    return obj
                    总结:你在书写中间件的时候 只要形参中有repsonse 你就顺手将其返回 这个reponse就是要给前端的消息
                    
                    
                    如何自定义我们自己的中间件,研究这上面五个方法都有哪些特点
                            1.如果你想让你写的中间件生效 就必须要先继承MiddlewareMixin
                            2.在注册自定义中间件的时候 一定要确保路径不要写错
    代码:
     1 class MyMdd(MiddlewareMixin):
     2     def process_request(self,request):
     3         print('我是第一个中间件里面的process_request方法')
     4 
     5 
     6     def process_response(self,request,response):
     7         print('我是第一个中间件里面的process_response方法')
     8         return response
     9 
    10     def process_view(self,request,view_func,view_args,view_kwargs):
    11         print(view_func)
    12         print(view_args)
    13         print(view_kwargs)
    14         print('我是第一个中间件里面的process_view方法')
    15 
    16     def process_exception(self, request, exception):
    17         print('我是第一个中间件里面的process_exception')
    18 
    19     def process_template_response(self, request, response):
    20         print('我是第一个中间件里面的process_template_response')
    21         return response
    22 
    23 
    24 class MyMdd1(MiddlewareMixin):
    25     def process_request(self,request):
    26         print('我是第二个中间件里面的process_request方法')
    27 
    28     def process_response(self,request,response):
    29         print('我是第二个中间件里面的process_response方法')
    30         return response
    31     def process_view(self,request,view_func,view_args,view_kwargs):
    32         print(view_func)
    33         print(view_args)
    34         print(view_kwargs)
    35         print('我是第二个中间件里面的process_view方法')
    36 
    37 
    38     def process_exception(self, request, exception):
    39         print('我是第二个中间件里面的process_exception')
    40 
    41     def process_template_response(self, request, response):
    42         print('我是第二个中间件里面的process_template_response')
    43         return response
    View Code

    2.csrf跨站请求伪造:

    什么是钓鱼网站:
        就是通过制作一个跟正儿八经的网站一模一样的页面,
        骗取用户输入信息,转账交易,从而做手脚 案例: 比如说转账交易的请求确确实实是发给了中国银行,
    账户钱也确确实实少了,唯一不一样的是收款人的账户不对。 内部的原理: 在让用户输入对方账户的那个input框上面做手脚,给这个input框不设置name属性,
    在内部隐藏一个事先写好的name和value属性的input框,这个value的值,就是钓鱼网站受益人的账号 防止钓鱼网站的思路: 网站会给返回的用户的form表单页面,偷偷塞一个随机字符串,
    请求到来的时候,会先比对随机字符串是否一致,如果不一致,直接拒绝(
    403) 这就解释了为什么以前每一次都把中间件的一个中间件给注释了。 该随时字符串有一下特点: 1.同一个浏览器每一次访问都不一样 2.不同的浏览器绝对不会重复

    正规网站:

    后端:

    1 def transfer(request):
    2     if request.method == 'POST':
    3         username = request.POST.get('username')
    4         money = request.POST.get('money')
    5         target_user = request.POST.get('target_user')
    6         print('%s 给 %s 转了 %s元'%(username,target_user,money))
    7     return render(request,'t.html')
    View Code

    前端:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6     <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
     7 </head>
     8 <body>
     9 <h2>这是正儿八经的网站</h2>
    10 <form action="" method="post">
    11     {% csrf_token %} 
    12     <p>本人用户名:<input type="text" name="username"></p>
    13     <p>转账金额:<input type="text" name="money"></p>
    14     <p>对方账户:<input type="text" name="target_user"></p>
    15     <input type="submit">
    16 </form>
    17 
    18 </body>
    19 </html>
    View Code

    钓鱼网站:

    前端:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6     <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
     7 </head>
     8 <body>
     9 <h2>这是钓鱼网站</h2>
    10 <form action="http://127.0.0.1:8000/transfer/" method="post">
    11     <p>本人用户名:<input type="text" name="username"></p>
    12     <p>转账金额:<input type="text" name="money"></p>
    13     <p>对方账户:<input type="text"></p>
    14     <input type="text" name="target_user" value="jason" style="display: none">
    15     <input type="submit">
    16 </form>
    17 </body>
    18 </html>
    View Code

    总结:1.form表单发送post请求的时候,需要你做的仅仅就是书写一句话:{% csrf_token %}

    2.Ajax发送post请求时,该如何避免csrf校验

    前端:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6     <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
     7 </head>
     8 <body>
     9 <h2>这是正儿八经的网站</h2>
    10 <form action="/lll/" method="post">
    11 {#    {% csrf_token %}#}
    12     <p>本人用户名:<input type="text" name="username"></p>
    13     <p>转账金额:<input type="text" name="money"></p>
    14     <p>对方账户:<input type="text" name="target_user"></p>
    15     <input type="submit">
    16 </form>
    17 {#<button id="b1">发送ajax请求</button>#}
    18 
    19 {% load static %}
    20 {#<script src="{% static 'setjs.js' %}"></script>#}
    21 <script>
    22     {#$('#b1').click(function () {#}
    23     {#    $.ajax({#}
    24     {#        url:'',#}
    25     {#        type:'post',#}
    26     {#        // 第一种方式#}
    27             {#data:{'username':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},#}
    28     {#        // 第二种方式#}
    29             {#data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
    30     {#        // 第三种方式 :直接引入js文件#}
    31     {#        data:{'username':'jason'},#}
    32     {#        success:function (data) {#}
    33     {#            alert(data)#}
    34     {#        }#}
    35     {##}
    36     {#    })#}
    37     // {})
    38 </script>
    39 </body>
    40 </html>
    View Code
        1.现在页面上写{% csrf_token %},利用标签查找  获取到该input键值信息
                    {'username':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}
                    $('[name=csrfmiddlewaretoken]').val()
                    
                2.直接书写'{{ csrf_token }}'
                    {'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}
                    {{ csrf_token }}
                
                3.你可以将该获取随机键值对的方法 写到一个js文件中,之后只需要导入该文件即可
                    新建一个js文件 存放以下代码 之后导入即可 
      导入的代码:
     1 function getCookie(name) {
     2                     var cookieValue = null;
     3                     if (document.cookie && document.cookie !== '') {
     4                         var cookies = document.cookie.split(';');
     5                         for (var i = 0; i < cookies.length; i++) {
     6                             var cookie = jQuery.trim(cookies[i]);
     7                             // Does this cookie string begin with the name we want?
     8                             if (cookie.substring(0, name.length + 1) === (name + '=')) {
     9                                 cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
    10                                 break;
    11                             }
    12                         }
    13                     }
    14                     return cookieValue;
    15                 }
    16                 var csrftoken = getCookie('csrftoken');
    17 
    18 
    19                 function csrfSafeMethod(method) {
    20                   // these HTTP methods do not require CSRF protection
    21                   return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    22                 }
    23 
    24                 $.ajaxSetup({
    25                   beforeSend: function (xhr, settings) {
    26                     if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
    27                       xhr.setRequestHeader("X-CSRFToken", csrftoken);
    28                     }
    29                   }
    30                 });
    31         
    View Code

    1.当你网站全局都需要校验csrf的时候,有几个不需要校验该如何处理:

    2.当你网站全局不校验csrf的时候 有几个需要校验又该如何处理 :

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    1.@csrf_exempt
    def login(request):
        return HttpResponse('login')
    
    
    2.@csrf_protect
    def lll(request):
        return HttpResponse('lll')

    在CBV中该如何装饰:

    from django.utils.decorators import method_decorator    
                from django.views.decorators.csrf import csrf_exempt,csrf_protect
                # 这两个装饰器在给CBV装饰的时候 有一定的区别
                如果是csrf_protect 那么有三种方式
                    # 第一种方式
                    # @method_decorator(csrf_protect,name='post')  # 有效的
                    class MyView(View):
                        # 第三种方式
                        # @method_decorator(csrf_protect)
                        def dispatch(self, request, *args, **kwargs):
                            res = super().dispatch(request, *args, **kwargs)
                            return res
    
                        def get(self,request):
                            return HttpResponse('get')
                        # 第二种方式
                        # @method_decorator(csrf_protect)  # 有效的
                        def post(self,request):
                            return HttpResponse('post')
                        
                如果是csrf_exempt 只有两种(只能给dispatch装)   特例
                @method_decorator(csrf_exempt,name='dispatch')  # 第二种可以不校验的方式
                class MyView(View):
                    # @method_decorator(csrf_exempt)  # 第一种可以不校验的方式
                    def dispatch(self, request, *args, **kwargs):
                        res = super().dispatch(request, *args, **kwargs)
                        return res
    
                    def get(self,request):
                        return HttpResponse('get')
    
                    def post(self,request):
                        return HttpResponse('post')

    总结 装饰器中只有csrf_exempt是特例,其他的装饰器在给CBV装饰的时候 都可以有三种方式

    auth模块:

    auth模块
                如果你想用auth模块   那么你就用全套
                
                
                
                跟用户相关的功能模块
                    用户的注册 登陆 验证 修改密码 ...
                
                执行数据库迁移命令之后  会生成很多表  其中的auth_user是一张用户相关的表格
                添加数据
                    createsuperuser  创建超级用户 这个超级用户就可以拥有登陆django admin后台管理的权限
            
    
            auth模块的功能
                查询用户
                    from django.contrib import auth
                    user_obj = auth.authenticate(username=username,password=password)  # 必须要用 因为数据库中的密码字段是密文的 而你获取的用户输入的是明文
                记录用户状态
                    auth.login(request,user_obj)  # 将用户状态记录到session中
                判断用户是否登录
                    print(request.user.is_authenticated)  # 判断用户是否登录  如果是你们用户会返回False
                用户登录之后 获取用户对象
                    print(request.user)  # 如果没有执行auth.login那么拿到的是匿名用户
                校验用户是否登录
                    from django.contrib.auth.decorators import  login_required
                    @login_required(login_url='/xxx/')  # 局部配置
                    def index(request):
                        pass
                    
                    # 全局配置  settings文件中
                    LOGIN_URL = '/xxx/'
                验证密码是否正确
                    request.user.check_password(old_password)
                修改密码    
                    request.user.set_password(new_password)
                    request.user.save()  # 修改密码的时候 一定要save保存 否则无法生效
                退出登陆
                    auth.logout(request)  # request.session.flush()
                注册用户
                        # User.objects.create(username =username,password=password)  # 创建用户名的时候 千万不要再使用create 了
                        # User.objects.create_user(username =username,password=password)  # 创建普通用户
                        User.objects.create_superuser(username =username,password=password,email='123@qq.com')  # 创建超级用户  邮箱必填
            
            
            自定义auth_user表
                from django.contrib.auth.models import AbstractUser
                # Create your models here.
                # 第一种 使用一对一关系  不考虑
    
    
    
                # 第二种方式   使用类的继承
                class Userinfo(AbstractUser):
                    # 千万不要跟原来表中的字段重复 只能创新
                    phone = models.BigIntegerField()
                    avatar = models.CharField(max_length=32)
                
                # 一定要在配置文件中 告诉django
                # 告诉django  orm不再使用auth默认的表  而是使用你自定义的表
                AUTH_USER_MODEL = 'app01.Userinfo'  # '应用名.类名'
            
    from django.contrib.auth.decorators import  login_required
    @login_required # 自动校验当前用户是否登录 如果没有登录 默认跳转到 一个莫名其妙的登陆页面
    1.执行数据库迁移命令 所有的auth模块功能 全部都基于你创建的表 而不再使用auth_user

      

  • 相关阅读:
    easyui使用datagrid时列名包含特殊字符导致表头与数据错位的问题
    解析:使用easyui的form提交表单,在IE下出现类似附件下载时提示是否保存的现象
    使用PreApplicationStartMethodAttribute
    Entity Framework使用Sqlite时的一些配置
    如何自己编写一个easyui插件续
    如何自己编写一个easyui插件
    启动报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
    Tomcat启动报错:java.net.BindException: Cannot assign requested address: JVM_Bind
    Maven项目Eclipse启动时报错: java.lang.ClassNotFoundException: org.springframework.web.util.IntrospectorCleanupListener
    ORA-12519, TNS:no appropriate service handler found(数据库上当前的连接数目已经超过最大值)
  • 原文地址:https://www.cnblogs.com/zahngyu/p/11587914.html
Copyright © 2011-2022 走看看