zoukankan      html  css  js  c++  java
  • Django Middleware 中间件

    Django  Middleware 中间件

    中间件字符串导入方式
    settins.py -> MIDDLEWARE 中间件的放置位置

    用户请求时,最先是从中间件,全部按顺序执行
    中间件又有两种,接收和返回的

    1. 接收请求的中间件,request
    2. 返回请求的中间件, response

    请求过来:

    1. 中间件:拦截一部分请求;比如验证session, 没有登录的 请求一些页面,跳转至登录页;(图片为中间件的请求过程.)
      2 .再到 urls ,分发请求
      3 .到views 视图 ,通过 CBV(dispatch反射) 和 FBV 的 get 请求 讲 template 页面渲染返回给用户;
    2. 渲染之前 可以从数据库拿出数据,放到render 的参数里面传递过去, locals() 表示 把所有参数传递
      还可以 实例化 其他 form 类,并渲染给前端
    • 可以应用于:
      • 请求日志
      • 用户登录认证
      • 各种跳转
      • 防火墙

    自定义中间件

    settins.py -> MIDDLEWARE 先去注册到里面才可以应用
    django 1.11 以后
    form djang.utils.deprecation import MiddlewareMixin
    这个就没了,需要手动自己写到你的自定义的文件里去

    settings.py

    from django.middleware.common import CommonMiddleware
    
    white_list = ['/login_demo/']   # 白名单机制, 不用验证session 信息
    
    #中间件
    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',
        'md.middleware.MiddlewareLogin',   # 注册
    ]
    

    自定义的 中间件 -> middleware.py

    class MiddlewareMixin(object):
        def __init__(self, get_response=None):
            self.get_response = get_response
            super(MiddlewareMixin, self).__init__()
    
        def __call__(self, request):
            response = None
            if hasattr(self, 'process_request'):
                response = self.process_request(request)
            if not response:
                response = self.get_response(request)
            if hasattr(self, 'process_response'):
                response = self.process_response(request, response)
            return response
    
    
    #自己写的中间件需要 手动去继承它 MiddlewareMixin
    
    class Middleware_hc_login(MiddlewareMixin):
        def process_request(self, request):
            print ('你需要自定义的代码,写在这')
            if not request.META.get('PATH_INFO') in white_list:
                if not request.session.get('login'):
                    return redirect('/login')
    
        def process_response(self, response):
            print ('这个是你的response返回,必须最后带上return返回')
            print ('一般可以不写这个response,只要写request就可以了')
            return response 
    

    白名单机制

    white_list = ['/login']      #  如果是登录的话,这个白名单就不会判断session
    
    if not request.META.get('PATH_INFO') in white_list:
        if not request.session.get('login'):
            return redirect('/login')
    
    

    关于请求头部信息

    Header 和 request.META
    request.META 是一个Python字典,包含了所有本次HTTP请求的Header信息,比如用户IP地址和用户Agent(通常是浏览器的名称和版本号)。 注意,Header信息的完整列表取决于用户所发送的Header信息和服务器端设置的Header信息。

    这个字典中几个常见的键值有:

    HTTP_REFERER
    进站前链接网页,如果有的话。 (请注意,它是REFERRER的笔误。)

    HTTP_USER_AGENT
    用户浏览器的user-agent字符串,如果有的话。 例如: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17" .

    REMOTE_ADDR
    客户端IP,如:"12.345.67.89" 。(如果申请是经过代理服务器的话,那么它可能是以逗号分割的多个IP地址,如:"12.345.67.89,23.456.78.90" 。)

    那么 request.META 里面还有什么有用的数据呢?动手写一个简单的view函数来显示 request.META 的所有数据,这样你就知道里面有什么了。

    def display_meta(request):
        values = request.META.items()
        values.sort()
        html = []
        for k, v in values:
            html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v))
        return HttpResponse('<table>%s</table>' % '
    '.join(html))
    

    结果如下:

    ALLUSERSPROFILE C:ProgramData
    APPDATA C:Usersl3591AppDataRoaming
    COMMONPROGRAMFILES  C:Program FilesCommon Files
    COMMONPROGRAMFILES(X86) C:Program Files (x86)Common Files
    COMMONPROGRAMW6432  C:Program FilesCommon Files
    COMPUTERNAME    HC
    COMSPEC C:WINDOWSsystem32cmd.exe
    DJANGO_SETTINGS_MODULE  hc_learning.settings
    DRIVERDATA  C:WindowsSystem32DriversDriverData
    FPS_BROWSER_APP_PROFILE_STRING  Internet Explorer
    FPS_BROWSER_USER_PROFILE_STRING Default
    HOMEDRIVE   C:
    HOMEPATH    Usersl3591
    LOCALAPPDATA    C:Usersl3591AppDataLocal
    LOGONSERVER \HC
    NUMBER_OF_PROCESSORS    8
    ONEDRIVE    C:Usersl3591OneDrive
    ONLINESERVICES  Online Services
    OS  Windows_NT
    PATH    D:python3.7Scripts;D:python3.7;C:Program Files (x86)IntelIntel(R) Management Engine ComponentsiCLS;C:Program FilesIntelIntel(R) Management Engine ComponentsiCLS;C:windowssystem32;C:windows;C:windowsSystem32Wbem;C:windowsSystem32WindowsPowerShellv1.0;C:Program Files (x86)IntelIntel(R) Management Engine ComponentsDAL;C:Program FilesIntelIntel(R) Management Engine ComponentsDAL;C:Program Files (x86)IntelIntel(R) Management Engine ComponentsIPT;C:Program FilesIntelIntel(R) Management Engine ComponentsIPT;C:Program Files (x86)NVIDIA CorporationPhysXCommon;C:Program FilesGitcmd;C:WINDOWSsystem32;C:WINDOWS;C:WINDOWSSystem32Wbem;C:WINDOWSSystem32WindowsPowerShellv1.0;C:WINDOWSSystem32OpenSSH;C:Program FilesIntelWiFiin;C:Program FilesCommon FilesIntelWirelessCommon;D:python3Scripts;D:python3
    PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
    PLATFORMCODE    KV
    PROCESSOR_ARCHITECTURE  AMD64
    PROCESSOR_IDENTIFIER    Intel64 Family 6 Model 142 Stepping 10, GenuineIntel
    PROCESSOR_LEVEL 6
    PROCESSOR_REVISION  8e0a
    PROGRAMDATA C:ProgramData
    PROGRAMFILES    C:Program Files
    PROGRAMFILES(X86)   C:Program Files (x86)
    PROGRAMW6432    C:Program Files
    PSMODULEPATH    C:Program FilesWindowsPowerShellModules;C:WINDOWSsystem32WindowsPowerShellv1.0Modules
    PUBLIC  C:UsersPublic
    PYCHARM D:pycharmPyCharm 2018.3in;
    PYCHARM_HOSTED  1
    PYCHARM_MATPLOTLIB_PORT 59802
    PYTHON3 D:python3.7python.exe
    PYTHONIOENCODING    UTF-8
    PYTHONPATH  C:Usersl3591Desktophc_learning;D:pycharmPyCharm 2018.3helperspycharm_matplotlib_backend
    PYTHONUNBUFFERED    1
    REGIONCODE  APJ
    SESSIONNAME Console
    SYSTEMDRIVE C:
    SYSTEMROOT  C:WINDOWS
    TEMP    C:Usersl3591AppDataLocalTemp
    TMP C:Usersl3591AppDataLocalTemp
    USERDOMAIN  HC
    USERDOMAIN_ROAMINGPROFILE   HC
    USERNAME    hc
    USERPROFILE C:Usersl3591
    WINDIR  C:WINDOWS
    RUN_MAIN    true
    SERVER_NAME hc
    GATEWAY_INTERFACE   CGI/1.1
    SERVER_PORT 8000
    REMOTE_HOST 
    CONTENT_LENGTH  
    SCRIPT_NAME 
    SERVER_PROTOCOL HTTP/1.1
    SERVER_SOFTWARE WSGIServer/0.2
    REQUEST_METHOD  GET
    PATH_INFO   /meta
    QUERY_STRING    
    REMOTE_ADDR 127.0.0.1
    CONTENT_TYPE    text/plain
    HTTP_HOST   127.0.0.1:8000
    HTTP_CONNECTION keep-alive
    HTTP_CACHE_CONTROL  max-age=0
    HTTP_UPGRADE_INSECURE_REQUESTS  1
    HTTP_USER_AGENT Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0
    HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*'/'*;q=0.8
    HTTP_ACCEPT_ENCODING    gzip, deflate, sdch, br
    HTTP_ACCEPT_LANGUAGE    zh-CN,zh;q=0.8
    HTTP_COOKIE csrftoken=AOFQMm36wEvD2Y2TrPgnS4RhBWRo3kcic1UScGKDFZ7sUJDOQfGgBlX1HKqZY1CN
    wsgi.input  <_io.BufferedReader name=996>
    wsgi.errors <_io.TextIOWrapper name='' mode='w' encoding='UTF-8'>
    wsgi.version    (1, 0)
    wsgi.run_once   False
    wsgi.url_scheme http
    wsgi.multithread    True
    wsgi.multiprocess   False
    wsgi.file_wrapper   
    

    解析客户端IP 并判断是否存在代理

    通常访问者的IP就在其中,所以我们可以用下列方法获取用户的真实IP:

    #X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,
    #只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。
    
    def get_ip(request):
       
         x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        
         if x_forwarded_for:
            
               ip = x_forwarded_for.split(',')[0]     #所以这里是真实的ip
        
         else:
            
               ip = request.META.get('REMOTE_ADDR')#这里获得代理ip
        return ip

    扩展


    中间件运用
    -权限
    -用户登录验证
    -django的csrf_token 如何实现
    csrf_token 验证在 process_view 方法里面
    检查 视图是否被 @csrf_exempt (免除csrf认证)
    去请求体 或 cookie 中获取token

    两种 设置的方式
    一种通过 装饰器
    一种通过 中间件


    1. process_request # 进
    2. prrcess_view # 视图
    3. process_response # 出
    4. process_exception # 处理异常
    5. process_render_template # 如果有template方法就会返回

    请求流程

    用户 -> process_request -> url路由匹配到了,但没执行 -> 跳转回中间件开头再从头走一遍到到 -> process_request -> 再到执行的views视图执行

    执行完定义的逻辑 从 process_response 出去
    如果中间有异常 会直接走 process_exception 处理返回异常
    如果有template 就会走 process_render_template


    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    @csrf_protect # 需要验证csrf_token认证
    @csrf_exempt # 免除csrf_token认证

     
  • 相关阅读:
    类和迭代器
    使用委托调用函数
    自定义类和集合
    带函数的参数返回函数的最大值
    使用程序调试输出窗口
    自定义类
    类和结构
    全局参数
    带参数的函数返回数组之和
    IS运算符
  • 原文地址:https://www.cnblogs.com/huidou/p/10757904.html
Copyright © 2011-2022 走看看