zoukankan      html  css  js  c++  java
  • rbac权限+中间件

    1、什么是权限

    1 项目与应用

    2 什么是权限?

    一个包含正则表达式url就是一个权限

    who what how ---------->True or Flase

    2、版本: 用户--》角色--》权限

    复制代码
        UserInfor
         
             name       
             pwd
             roles
            
            
            
            name   pwd    
            egon   123            
            alex   456    
            alex   456    
            alex   456    
            alex   456    
            alex   456    
            alex   456    
            alex   456    
            alex   456    
            
                
        Role
           
           title=.......       
           permissions=......
           
             id   title
             1   销售员
           
        
        UserInfor2Role
    
           id     user_id    role_id    
            1        1          1
    
            
        Permission
         
            url=.....
              title=....
            
        id       url            title
        1     "/users/"         "查看用户"
        2     "/users/add/"     "添加用户"
         3    "/customer/add"    "添加客户"
             
        
             
             
        Role2Permission
    
        id  role_id   permission_id    
         1      1           1
         2      1           2
         3      1           3
             
             
             
        3  rbac(role-based access control) 
         
         
    复制代码

     3.数据表的初步设计

    from django.db import models
    
    # Create your models here.
    
    class User(models.Model):              #用户表
        name=models.CharField(max_length=32)
        pwd=models.CharField(max_length=32)
        roles=models.ManyToManyField(to="Role")        #一个用户可以有多个角色,一个角色可以为多个用户所拥有。
        def __str__(self):
            return self.name
    
    class Role(models.Model):
        title=models.CharField(max_length=32)       
        permissions=models.ManyToManyField(to="Permission") #一个角色有多个权限,一个权限也可以是多个角色拥有。
    
        def __str__(self):
            return self.title
    
    class Permission(models.Model):
        title=models.CharField(max_length=32)    #权限明珠城
        url=models.CharField(max_length=32)      #权限的url
    
        action=models.CharField(max_length=32,default="")  #权限操作(add,list,edit,delete)
        group=models.ForeignKey("PermissionGroup",default=1,on_delete=models.CASCADE)
        def __str__(self):
            return self.title
    
    class PermissionGroup(models.Model):
        title=models.CharField(max_length=32)
    
        def __str__(self):
            return self.title
     

    1)项目目录结构

    2)数据库表

     3)admin添加数据

    创建超级用户 alex

     注册数据表

    from django.contrib import admin
    
    # Register your models here.
    
    
    from .models import *
    
    admin.site.register(User)
    admin.site.register(Role)
    admin.site.register(Permission)

     4、登录验证

    1、session中注册用户,权限

    1.在session中注册用户ID
    request.session['user_id'] = user.pk
    2.初始化 permission_list 并注册到session 中
    initial_session(user,request)
            if 登录成功:
                user=User.objects.filter(name=user,pwd=pwd).first()
                只要这个user对象存在
                initial_session(user,request)通过传入登录的user对象和request
                可以把当前登录用户的权限列表和user_id注册到session中。
            else:
                redirect("/login/")
    
        ** 把设置session单独做成一个函数接口降低耦合,只需要传入登录用户的对象。
            def initial_session(user,request):
            permissions = user.roles.all().values("permissions__url").distinct()
            #通过登录用户对象查找到所有的角色对象QuerySet,然后跨表到权限表取到URL,做一个去重
     <QuerySet [{'permissions__url': '/users/'}, {'permissions__url': '/users/add'},  {'permissions__url': '/users/delete/(\d+)'}]>

    注意点:

    permission = user.roles.all().values('permission__url').distinct()
     #将这些权限取到对应的URL并且添加到列表中,设置在session中。
     permission_list = []
     for item in permissions:
         permission_list.append(item["permissions__url"])
     print(permission_list)
     request.session["permission_list"] = permission_list

    2、解耦

     

     
    def initial_session(request,user):
        permissions = user.roles.all().values("permissions__url").distinct()
    
        permission_list = []
        for item in permissions:
            permission_list.append(item['permissions__url'])
    
        print(permission_list)  # ['/users/', '/users/add', '/users/delete/(\d+)', '/users/edit/(\d+)']
    
        request.session["permission_list"] = permission_list
    
    
        """
        values :
    
        for role in user.roles.all():   # <QuerySet [<Role: 保洁>, <Role: 销售>]>
            temp.append({
            "title":role.title,
            "permissions_url":role.permissions.all()
            })
    
        # <QuerySet [{'title': '保洁', 'permissions__url': '/users/'},
        # {'title': '销售', 'permissions__url': '/users/'},
        # {'title': '销售', 'permissions__url': '/users/add'}]>
    
        """
     

     

     

    4、基于中间件的权限校验

    1、middleware如何构造

     设置中添加中间件"rbac.service.rbac.ValidPermissionMiddleware"

    2、正则匹配

     
    from django.test import TestCase
    
    # Create your tests here.
    
    # 当前path 如何与 paths匹配
    # 不能用in   /users/delete/9
    # 正则匹配
    
    
    li = ['/users/', '/users/add', '/users/delete/(\d+)', '/users/edit/(\d+)']
    
    c_path = "/users/delete/9"
    
    import re
    
    flag = False
    
    for permission in li:
        permission = "^%s$" % permission
        ret = re.match(permission, c_path)
        if ret:
            flag = True
            break
    
    if flag:
        print("success")
    
    # ret = re.match("/users/", "/users/delete/9")
    ret = re.match("^/users/$", "/users/delete/9")
    print(ret)
     

    3、构建中间件

     

            import re
            from django.utils.deprecation import MiddlewareMixin
            from django.shortcuts import  HttpResponse,redirect
    
            class ValidPermissionMiddleWare(MiddlewareMixin):
                def process_request(self,request):
                    # 当前访问路径
                    current_path = request.path_info
    
                    #1层校验 检查是否属于白名单
                    valid_url_list=["/login/","/reg/","/admin/.*"]
                    for valid_url in valid_url_list:
                        ret=re.match(valid_url,current_path)
                        if ret:
                            return None
    
                    #2层校验 校验是否登录
                    user_id=request.session.get("user_id")
                    if not user_id:
                        return redirect("/login/")
    
                    # 3层校验校验权限
                    permission_list = request.session.get("permission_list",[])   
                    #['/users/', '/users/add', '/users/delete/(\d+)', 'users/edit/(\d+)']
    
                    flag = False
                    for permission in permission_list:
                        #此处做一个RE拼接,不然容易匹配失败
                        permission = "^%s$" % permission
                        ret = re.match(permission, current_path)
                        if ret:
                            flag = True
                            break
                    if not flag:
                        return HttpResponse("没有访问权限!")
                        #在此处就直接告诉用户没有权限,不再进入视图。
                    return None

     4、views视图,url

    url.py

     
    from django.contrib import admin
    from django.urls import path,re_path
    
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^users/$',views.users),
        re_path(r'^users/add/$',views.add_user),
        re_path(r'^roles/$',views.roles),
        re_path(r'^login/$',views.login),
    ]
     

    views

     
    from django.shortcuts import render, HttpResponse
    
    # Create your views here.
    
    from rbac.models import *
    
    
    def users(request):
        user_list = User.objects.all()
    
        return render(request, "users.html", locals())
    
    
    def add_user(request):
    
        """
        permission_list = request.session["permission_list"]  # # ['/users/', '/users/add', '/users/delete/(\d+)', '/users/edit/(\d+)']
        current_path = request.path_info
    
        flag = False
        for permission in permission_list:
            permission = "^%s$"%permission
            ret = re.match(permission, current_path)
            if ret:
                flag = True
                break
    
        if not flag:
            return  HttpResponse("没有访问权限")
        """
        return HttpResponse('add user')
    
    
    def roles(request):
        role_list = Role.objects.all()
        print(role_list)
    
        # 方式2 middleware
    
    
        """
        # 方式1
        permission_list = request.session["permission_list"]  # # ['/users/', '/users/add', '/users/delete/(\d+)', '/users/edit/(\d+)']
        current_path = request.path_info
    
        flag = False
        for permission in permission_list:
            permission = "^%s$"%permission
            ret = re.match(permission, current_path)
            if ret:
                flag = True
                break
    
        if not flag:
            return  HttpResponse("没有访问权限")
        """
    
        return render(request, "roles.html", locals())
    
    
    from rbac.service.perssions import *
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
    
            user = User.objects.filter(name=user, pwd=pwd).first()
            if user:
    
                ############## 在session中注册用户
                request.session['user_id'] = user.pk
    
    
                ############# 在session中注册权限list
    
                # 查询当前登录用户的所有角色
                # ret = user.roles.all()
                # print(ret)   # <QuerySet [<Role: 保洁>, <Role: 销售>]>
    
                # 查询当前登录用户的所有权限
    
                initial_session(request, user)
    
                return HttpResponse("登录成功")
    
    
        return render(request, 'login.html', locals())
     

    注意点

    1.白名单,不需要任何权限的url
    valid_url_list = ['/login/', '/reg/', '/admin/.*']
    for valid_url in valid_url_list:
    ret = re.match(valid_url, current_path)
    if ret:
    return

    正则匹配

    2.校验是否登录,
    user_id = request.session.get('user_id')
    if not user_id:
    return redirect('/login/')

    3.校验权限(^ $ / 正则)
    permission_list = request.session.get('permission_list',[])

    flag = False
    for permission in permission_list:
    # ['/users/', '/users/add/', '/users/edit/(\d+)/', '/users/delete/(\d+)/']
    # 需要 ^ $ 限定!!
    permission = "^%s$" % permission

    # 正则
    ret = re.match(permission, current_path)
    if ret:
    flag = True
    break

    if not flag:
    return HttpResponse('无访问权限!')
     

    4、总结:关于rbac

     
    关于rbac: 
    
        (1) 创建表关系:
            class User(models.Model):
                name=models.CharField(max_length=32)
                pwd=models.CharField(max_length=32)
                roles=models.ManyToManyField(to="Role")
    
                def __str__(self): return self.name
    
            class Role(models.Model):
                title=models.CharField(max_length=32)
                permissions=models.ManyToManyField(to="Permission")
    
                def __str__(self): return self.title
    
            class Permission(models.Model):
                title=models.CharField(max_length=32)
                url=models.CharField(max_length=32)
    
                def __str__(self):return self.title
        
        (2) 基于admin录入数据
    
    
        (3) 登录校验:
            
            if 登录成功:
               
                查询当前登录用户的权限列表注册到session中
    
        (4) 校验权限(中间件的应用)
            class ValidPermission(MiddlewareMixin):
    
                def process_request(self,request):
    
                    # 当前访问路径
                    current_path = request.path_info
    
                    # 检查是否属于白名单
                    valid_url_list=["/login/","/reg/","/admin/.*"]
    
                    for valid_url in valid_url_list:
                        ret=re.match(valid_url,current_path)
                        if ret:
                            return None
                    # 校验是否登录
    
                    user_id=request.session.get("user_id")
                    if not user_id:
                        return redirect("/login/")
    
                    # 校验权限
                    permission_list = request.session.get("permission_list",[])  # ['/users/', '/users/add', '/users/delete/(\d+)', 'users/edit/(\d+)']
    
    
                    flag = False
                    for permission in permission_list:
    
                        permission = "^%s$" % permission
    
                        ret = re.match(permission, current_path)
                        if ret:
                            flag = True
                            break
                    if not flag:
                        return HttpResponse("没有访问权限!")
                    return None

  • 相关阅读:
    Go 语言简介(下)— 特性
    Array.length vs Array.prototype.length
    【转】javascript Object使用Array的方法
    【转】大话程序猿眼里的高并发架构
    【转】The magic behind array length property
    【转】Build Your own Simplified AngularJS in 200 Lines of JavaScript
    【转】在 2016 年做 PHP 开发是一种什么样的体验?(一)
    【转】大话程序猿眼里的高并发
    php通过token验证表单重复提交
    windows 杀进程软件
  • 原文地址:https://www.cnblogs.com/geogre123/p/9789229.html
Copyright © 2011-2022 走看看