前后端分离进行权限管理之后端生成菜单和权限信息

Posted shenjianping

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前后端分离进行权限管理之后端生成菜单和权限信息相关的知识,希望对你有一定的参考价值。

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

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

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))

 

以上是关于前后端分离进行权限管理之后端生成菜单和权限信息的主要内容,如果未能解决你的问题,请参考以下文章

前后端分离学习笔记 --[权限分配案例]

前后端分离开发中动态菜单的两种实现方案

vue前后分离动态路由和权限管理方案

前后端分离权限控制设计和实现思路

SpringBoot+Shiro框架整合实现前后端分离的权限管理基础Demo

前后端分离学习笔记 ---[路由嵌套, 查询表单显示]