zoukankan      html  css  js  c++  java
  • django-中间件

    1.中间件的基本编写格式

    from django.conf import settings
    from django.shortcuts import redirect
    
    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
    
    
    class M1(MiddlewareMixin):
    
        def process_request(self,request,*args,**kwargs):
            # 如果当前的URL是 /login/ ,那就跳过该中间件的process_request方法
            # /login/?name=xxx
            # /login/
            if request.path_info == '/login/':
                return None
    
            # 排除/login/以外的所有URL,对用户认证。
            user_info = request.session.get(settings.USER_SESSION_KEY)
            if not user_info:
                # 未登陆
                return redirect('/login/')
    
            # 已登陆
    
        def process_response(self, request, response):
            print('m1.process_response')
            return response

    2.使用

    在settings中配置

    3.基于中间件的登录验证

    3.1 编写中间件

    import re
    
    from django.shortcuts import redirect,HttpResponse
    from django.conf import settings
    
    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
    
    class RbacMiddleware(MiddlewareMixin):
        def process_request(self,request):
            # 1. 获取当前请求的URL
            #    request.path_info
            # 2. 获取Session中保存当前用户的权限
            #    request.session.get("permission_url_list')
    
            # 获取当前的url请求
            current_url = request.path_info     # 当前请求的URL
    
            # 当前请求不需要执行权限验证   白名单机制
            for url in settings.WHITE_LIST:
                if re.match(url,current_url):
                    return None
    
            """
            {
                1:{
                    codes: [list,add,edit,del],
                    urls: [  /userinfo/,  /userinfo/add/,  /userinfo/... ]
                },
                2:{
                    codes: [list,add,edit,del],
                    urls: [  /userinfo/,  /userinfo/add/,  /userinfo/... ]
                }
                3:{
                    codes: [list,add,edit,del],
                    urls: [  /userinfo/,  /userinfo/add/,  /userinfo/... ]
                }
            }
            """
            # 获取Session中保存当前用户的权限,
            permission_dict = request.session.get(settings.PERMISSION_URL_DICT_KEY)
            # 判断是否有权限,无权限则跳转到登录页面
            if not permission_dict:
                return redirect('/rbac/login/')
            flag = False
            for group_id,code_url in permission_dict.items():
                for db_url in code_url['urls']:
                    regax = "^{0}$".format(db_url)
                    # match只要是..开头的都能匹配到,多以的加个^和$符
                    if re.match(regax, current_url):
                        # 获取当前用户对当前组内的所有code,并赋值给request
                        request.permission_code_list = code_url['codes']
                        flag = True
                        break
                if flag:
                    break
    
            if not flag:
                return HttpResponse('无权访问')

     3.2 在setting的MIDDLEWARE是中配置

    MIDDLEWARE = [
        ...
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'rbac.middlewares.rbac.RbacMiddleware',
    ]

    3.3 对登录信息保存session中

    from django.conf import settings
    
    def init_permission(user,request):
        """
        初始化权限信息,获取权限信息并放置到session中。
        :param user:
        :param request:
        :return:
        """
        permission_list = user.roles.filter(permissions__id__isnull=False).values(
                                'permissions__id',
                                'permissions__title',               # 用户列表
                                'permissions__url',                 # 含正则表达式的url
                                'permissions__code',                # 权限代码【list,add,del,edit】
                                'permissions__menu_gp_id',          # 组内菜单ID,Null表示是菜单
                                'permissions__group_id',            # 权限的组ID
                                'permissions__group__menu_id',      # 权限的组的菜单ID
                                'permissions__group__menu__title',  # 权限的组的菜单名称
                                ).distinct()
    
        # 菜单相关(以后再匹配),inclusion_tag,对菜单进行重新设置
        menu_permission_list = []
        for item in permission_list:
            tpl = {
                'id':item['permissions__id'],                            # 权限ID
                'title':item['permissions__title'],                     # 权限标题
                'url':item['permissions__url'],                         # 含正则表达式的url
                'menu_gp_id':item['permissions__menu_gp_id'],          # 菜组内菜单ID,Null表示是菜单
                'menu_id':item['permissions__group__menu_id'],         # 权限的组的菜单ID
                'menu_title':item['permissions__group__menu__title'], # 权限组的菜单名称
            }
            menu_permission_list.append(tpl)
        request.session[settings.PERMISSION_MENU_KEY] = menu_permission_list
    
        # 权限相关,中间件
        """
        {
            1:{
                codes: [list,add,edit,del],
                urls: [  /userinfo/,  /userinfo/add/,  /userinfo/... ]
            },
            2:{
                codes: [list,add,edit,del],
                urls: [  /userinfo/,  /userinfo/add/,  /userinfo/... ]
            }
            3:{
                codes: [list,add,edit,del],
                urls: [  /userinfo/,  /userinfo/add/,  /userinfo/... ]
            }
        }
        """
        result = {}
        for item in permission_list:
            group_id = item['permissions__group_id']    # 权限的组ID
            code = item['permissions__code']            # 权限代码【list,add,del,edit】
            url = item['permissions__url']              # 含正则表达式的url
            if group_id in result:
                result[group_id]['codes'].append(code)
                result[group_id]['urls'].append(url)
            else:
                result[group_id] = {
                    'codes':[code,],
                    'urls':[url,]
                }
    
        request.session[settings.PERMISSION_URL_DICT_KEY] = result

    3.4 配置url的白名单机制

    # rbac相关配置
    PERMISSION_MENU_KEY = "permission_menu_list"
    PERMISSION_URL_DICT_KEY = "permission_url_list"
    
    # ===白名单(不需要权限就可以看到的)
    WHITE_LIST= [
        '^/index/',
        '^/rbac/login/',
        '^/rbac/get_valid_img/',
        '^/logout/',
        "^/admin*",
    ]
  • 相关阅读:
    Lock wait timeout exceeded; try restarting transaction linux设置mysql innodb_lock_wait_timeout
    用NaviCat创建存储过程批量添加测试数据
    mysql存储过程语法及实例
    mysql中迅速插入百万条测试数据的方法
    mysql学习之通过文件创建数据库以及添加数据
    有用的网站集合
    VMware Workstation虚拟磁盘文件备份或移植
    CoreData修改了数据模型报错 The model used to open the store is incompatible with the one used to create the store
    iOS中自定义UITableViewCell的用法
    golang make()的第三个参数
  • 原文地址:https://www.cnblogs.com/goodshipeng/p/8202532.html
Copyright © 2011-2022 走看看