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