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*",
]

 

posted @ 2018-01-05 09:22  平凡执着  阅读(131)  评论(0编辑  收藏  举报