zoukankan      html  css  js  c++  java
  • 前后端分离进行权限管理之后端生成菜单和权限信息(二)

    一、初始化菜单、权限信息

    在进行用户名和密码验证成功后就进行权限和菜单的初始化,生成该用户的菜单和权限数据。

    class LoginView(APIView):
        authentication_classes = []  # 登陆页面免认证,其余的已经全局配置
    
        def post(self, request, *args, **kwargs):
    
            ret = {
                "data": {},
                "meta": {
                    "code": 2001,
                    "message": "用户名或密码错误"
                }
            }
            user_obj = json.loads(str(request._request.body, encoding='utf8'))
            username = user_obj.get('username')
            password = user_obj.get('password')
            if username and password:
                obj = UserInfo.objects.filter(
                    username=username, password=password).first()
                if obj:
                    #初始化权限、菜单信息
    
        
                    InitPermission(request,obj).init_menus_dict()
                    InitPermission(request,obj).init_permissions_dict()
                
                    # 生成token值
                    # token=str(uuid.uuid4()) #uuid生成token
                    token = get_md5(username)
                 
                    ret["data"]["username"] = username
                    ret["data"]["password"] = password
                    ret["data"]["token"] = token
                    # ret["data"]["permission_session_id"] = settings.PERMISSION_SESSION_KEY
                    # ret["data"]["menu_session_id"] = settings.MENU_SESSION_KEY
                    ret["meta"]["code"] = 2000
                    ret["meta"]["message"] = "登陆成功"
                else:
                    pass
            else:
                pass
            return HttpResponse(json.dumps(ret, ensure_ascii=False))

    二、生成菜单、权限信息

    通过将用户名传入Initpermission类中进行处理

    from rbac import models
    from django.conf import settings
    from crm.utils.session import SessionStore
    import json
    
    class InitPermission(object):
    
        def __init__(self, request, user):
            self.request = request
            self.user = user
            self.permissions_dict = {}
            self.menus_dict = {}
    
        def init_data(self):
            """
            从数据库中获取权限信息以及用户信息
            :return:
            """
            self.permissions_queryset = self.user.roles.filter(permissions__url__isnull=False).values(
                'permissions__id',
                'permissions__url',
                'permissions__title',
                'permissions__parent_id',
                'permissions__action__code',
                'permissions__menu_id',
                'permissions__menu__title',
                'permissions__menu__icon',
                'permissions__menu__position'
            ).distinct()
            return self.permissions_queryset
    
        def init_permissions_dict(self):
            """
                初始化权限,获取当前用户权限并添加到session中
            将当前用户权限信息转换为以下格式,并将其添加到Session中
            {
                '/index.html': ['GET','POST','DEL','EDIT],
                '/detail-(d+).html': ['GET','POST','DEL','EDIT],
            }
            :return:
            """
    
            for row in self.init_data():
                if row["permissions__url"] in self.permissions_dict:
                    self.permissions_dict[row["permissions__url"]].append(row["permissions__action__code"])
                else:
                    self.permissions_dict[row["permissions__url"]] = [row["permissions__action__code"], ]
            print('init',self.permissions_dict)
    
    #将权限信息存入redis,后续中间件中去除进行验证
     SessionStore().set_session(settings.PERMISSION_SESSION_KEY,self.permissions_dict)
            return self.permissions_dict
    
    
        def init_menus_dict(self):
            """
                   self.menus_dict={
                   1:{
                   title:'客户管理',icon:'fa fa-coffe',children:[
                   {'id':1,'url':'/customer/list/','title':'客户列表'}
                   ...
                   ]
                   }
                   }
                   :return:
            """
            for row in self.init_data():
                menu_id = row["permissions__menu_id"]
                if not menu_id:
                    continue
    
                if menu_id not in self.menus_dict:
                    self.menus_dict[row["permissions__menu__position"]] = {
                        "id":row["permissions__menu_id"],
                        "title": row["permissions__menu__title"],
                        "icon": row["permissions__menu__icon"],
                        "children": [
                            {
                                'id': row['permissions__id'],
                                 'title': row['permissions__title'],
                                 'url': row['permissions__url']
    
                            }
                        ]
                    }
    
                else:
                    self.menus_dict[row["permissions__menu__position"]]["children"].append(
                        {
                            'id': row['permissions__id'],
                            'title': row['permissions__title'],
                            'url': row['permissions__url']
    
                        }
                    )
    
            return self.menus_dict
    InitPermission

    其中菜单信息生成下述形式:

    {
        {
          'title': '用户管理',
          'icon': 'el-icon-location',
          'id': 1,
          'children': [{'title': '用户列表', 'url': '/crm/user', 'id': 1},
                       {'title': '部门列表', 'url': '/crm/dept', 'id': 11}
                       ]
          },
        {
            'title': '权限管理',
            'icon': 'el-icon-s-check',
            'id': 2,
             'children': [{'title': '权限列表', 'url': '/rbac/rights/list', 'id': 2},
                      {'title': '角色列表', 'url': '/rbac/roles', 'id': 7},
                      {'title': '菜单列表', 'url': '/crm/menus', 'id': 12}
                      ]
         }
     }

    权限信息生成以下形式:

    {
        '/crm/dept': ['get'], 
        '/crm/menus': ['get'], 
        '/rbac/roles': ['get'],
     '/rbac/roles/(?P<roleId>\d+)/permission$': ['put'],
        '/rbac/rights/list': ['get'],
     '/rbac/roles/(?P<roleId>\d+)/permission/(?P<permissionId>\d+)$': ['delete'],
        '/crm/user': ['get', 'post']
    }

    上面就是某一个用户所拥有的菜单以及权限信息。

    三、中间件进行权限校验

    from django.utils.deprecation import MiddlewareMixin
    from django.conf import settings
    import re
    from django.shortcuts import HttpResponse
    import json
    from crm.utils.session import SessionStore
    
    class RbacMiddleware(MiddlewareMixin):
    
        def process_request(self,request,*args,**kwargs):
    
            """跳过无需权限访问的URL"""
            # permission_dict = request.session.get(settings.RBAC_PERMISSION_SESSION_KEY)
            print('process_request',request.path_info)
    
            for pattern in settings.RBAC_NO_AUTH_URL:
    
                if re.match(pattern, request.path_info):
                    return None
    
            #从redis中获取permission_dict,是bytes类型
            permission_bytes = SessionStore().get_session(settings.PERMISSION_SESSION_KEY)
    
            permission_dict = eval(permission_bytes)
    if not permission_dict: return HttpResponse(json.dumps({"data": {}, "meta": {"message": "无权限访问", "code": 2002}})) #请求url与redis中存储的权限进行匹配 """     {'/rights': ['get'], '/user': ['get', 'post'], '/roles': ['get']} """ flag = False for pattern,code_list in permission_dict.items(): print('par,code...',pattern,request.path_info) upper_code_list=[item.upper() for item in code_list] request_permission_code = request.method if re.match(pattern,request.path_info): print(request_permission_code) print(upper_code_list) if request_permission_code in upper_code_list: permission_code_list = upper_code_list
    #将用户角色拥有的请求方式存储起来,传给前端进行按钮权限的验证 SessionStore().set_session(settings.PERMISSION_CODE_LIST_KEY,permission_code_list) flag = True breakif not flag: return HttpResponse(json.dumps({"data": {}, "meta": {"message": "rbac无权限访问", "code": 2002}}))
  • 相关阅读:
    下载flash我的三种方法
    随机变换背景图象(一个可以刷新心情的特效)
    禁止缓存
    [模板]字符串算法
    [学习笔记]有上下界的网络流
    [bzoj2809][Apio2012]dispatching
    [四校联考]Easy Problems
    [学习笔记]tarjan
    [vijos1780][NOIP2012]开车旅行
    记第一次打女队
  • 原文地址:https://www.cnblogs.com/shenjianping/p/11448427.html
Copyright © 2011-2022 走看看