zoukankan      html  css  js  c++  java
  • Django框架(十二)-- 中间件、CSRF跨站请求伪造

    中间件

    一、什么是中间件

    请求的时候需要先经过中间件才能到达django后端(urls,views,templates,models)

    响应的时候也需要经过中间件才能到达web服务网关接口

     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框架中做的最好的

    三、中间件执行顺序

    -process_request()方法,从上往下执行
            1.如果返回 HttpResponse对象,那么会直接返回,不再往下执行而是跳到同级别的process_response方法,直接往回走
            2.请求来的时候,会经过每个中间件里面的process_request方法(从上往下)
    -process_response,从下往上执行
            1.必须要将response形参返回,这个形参指代的就是要返回给前端的数据
            2.响应走的时候,会依次经过每一个中间件里面的process_response方法(从下往上)

     

     

     

     四、自定义中间件

    1.导包

    from django.utils.deprecation import MiddlewareMixin

    2.定义类,继承MiddlewareMixin

    在app01应用中创建一个文件夹mymiddleware,再创建一个mdd.py文件

    class MyMdd(MiddlewareMixin):
        def process_request(self,request):
            print('我是第一个中间件里面的process_request方法')
    
        def process_response(self,request,response):
            print('我是第一个中间件里面的process_response方法')
            return responseclass MyMdd1(MiddlewareMixin):
        def process_request(self,request):
            print('我是第二个中间件里面的process_request方法')
    
        def process_response(self,request,response):
            print('我是第二个中间件里面的process_response方法')
            return response

    3.定义视图函数

    def index(request):
        print("view函数...")
        return HttpResponse("OK")

    4.在settings中MIDDLEWARE注册自定义中间件

    MIDDLEWARE =[
         'mymiddleware.mdd.MyMdd',
         'mymiddleware.mdd.MyMdd1',
         'mymiddleware.mdd.MyMdd2',
    
    ]

    5.设置路由

    urlpatterns = [
        url(r'^index/',view.index)
    
    ]

    结果

    我是第一个中间件里面的process_request方法
    我是第二个中间件里面的process_request方法
    view函数...
    我是第二个中间件里面的process_response方法
    我是第一个中间件里面的process_response方法

    五、中间件五个可以自定义的方法

    需要掌握的方法:

    1.process_request()方法    请求来的时候会走该方法

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

    2.process_response()方法   响应回去的时候会走该方法

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

    需要了解的方法:

    3.process_view()

    在路由匹配成功执行视图函数之前 触发

    4.process_exception()

    当你的视图函数报错时,就会自动执行

    5.process_template_response()

    当你返回的HttpResponse对象中必须包含render属性才会触发
    def index(request):
        print('我是index视图函数')
        def render():
            return HttpResponse('什么鬼玩意')
        obj = HttpResponse('index')
        obj.render = render
        return obj

    总结:

    你在书写中间件的时候,只要形参中有response,你就应该顺手将其返回,这个response就是要给前端的信息。
    
    这五种方法有哪些特点:
    1.都需要继承MiddlewareMixin
    2.在注册中间件的时候,在settings中写的路径不能错

    CSRF——跨站请求伪造

    1.什么是CSRF攻击

    攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的。

    比如钓鱼网站

    2.CSRF攻击原理

    要完成一次CSRF攻击,受害者必须依次完成两个步骤:

      1.登录受信任网站A,并在本地生成Cookie。

      2.在不登出A的情况下,访问危险网站B。

    钓鱼网站例子

    通过制作一个跟正儿八经的网站一模一样的页面,骗取用户输入信息 转账交易从而做手脚
    转账交易的请求确确实实是发给了中国银行,账户的钱也是确确实实少了
    唯一不一样的地方在于收款人账户不对
    内部原理
        在让用户输入对方账户的那个input上面做手脚
        给这个input不设置name属性,在内部隐藏一个实现写好的name和value属性的input框
        这个value的值 就是钓鱼网站受益人账号

    如何区分钓鱼网站和正经网站?在正经网站返回页面的时候,在form表单中偷偷塞一个特殊的字符串,后端记下该页面对应的字符串的值,等用户发post请求来的时候,我先去校验特殊的字符串是否匹配

    如何去写这个特殊的字符串呢?模版语法有一个固定的写法{% csrf_token %},必须写在form表单内

    3.CSRF攻击防范

    防止钓鱼网站的思路
        网站会给用户访问的form表单页面 偷偷塞一个随机字符串
        请求到来的时候 会先比对随机字符串是否一致  如果不一致  直接拒绝(403)

    该随机字符串有以下特点
      1.同一个浏览器每一次访问都不一样
      2.不同浏览器绝对不会重复

    4.CSRF在Django中的应用

    1.在form表单中使用

    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <p>password:<input type="text" name="password"></p>
        <input type="submit">
    </form>

    2.在ajax中使用,如何避免csrf校验

    • 有两种方法,通过修改ajax的data

      方法一:先在form表单页面上写{% csrf_token%},利用标签查找,获取到该input键值消息

    data{'username':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}

      方法二:直接书写'{{csrf_token}}'

    data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}
    • 还可以将获取随机键值对的方法,写到一个js文件中,然后导入这个文件即可

      新建一个js文件,存放以下代码

    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                 // Does this cookie string begin with the name we want?
                 if (cookie.substring(0, name.length + 1) === (name + '=')) {
                     cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                     break;
                 }
            }
         }
         return cookieValue;
    }
    var csrftoken = getCookie('csrftoken');
    
    
    function csrfSafeMethod(method) {
       // these HTTP methods do not require CSRF protection
       return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
     }
    
    $.ajaxSetup({
         beforeSend: function (xhr, settings) {
           if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
             }
         }
     });

    5.CSRF禁用

    1.CSRF全局禁用

    注释掉settings中MIDDLEWARE的中间件 'django.middleware.csrf.CsrfViewMiddleware',

    2.CSRF局部禁用

    • 在FBV中,直接加载FBV就行了 (在页面不加csrf_token情况下)
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    #(前提是全局使用,没有注释csrf) 让这个不用校验,可以局部使用
    #当你网站全局需要校验csrf的时候,有几个不需要校验该如何处理 @csrf_exempt
    def login(request): return HttpResponse('login') #(前提是全局禁用,注释csrf,不会进行校验) 设置就会进行校验,局部禁用
    #当你网站全局不校验csrf的时候,有几个需要校验又该如何处理 @csrf_protect
    def lll(request): return HttpResponse('lll')
    • 在CBV中,只能在dispatch方法或者类上面
    from django.views import View
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    from django.utils.decorators import method_decorator
    # 这两个装饰器在给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')
  • 相关阅读:
    Core Animation笔记(变换)
    Core Animation笔记(- Layer 基本属性)
    使用AndroidStudio编写APICloud模块需要注意的地方,解决模块未定义。
    MAC中使用APICloud同步代码错误解决办法
    【深入理解Java虚拟机 】类加载器的命名空间以及类的卸载
    【深入理解Java虚拟机 】类的加载器
    【深入理解Java虚拟机】类的初始化过程
    Netty中ByteBuf的引用计数线程安全的实现原理
    Java使用PipedStream管道流通信
    Java中的守护线程
  • 原文地址:https://www.cnblogs.com/wangcuican/p/11587299.html
Copyright © 2011-2022 走看看