zoukankan      html  css  js  c++  java
  • 1、rbac权限组件-初识, 中间件校验1

    1、权限组件rbac

    1、什么是权限

    1 项目与应用

    2 什么是权限?

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

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

    2、版本1:用户表与权限url表 对应关系

        # 版本1
    
         UserInfor
         
             name       
             pwd
             permission=models.manytomany(Permission)
            
            
            name   pwd    
            egon   123            
            alex   456    
            A      111
            B      222
            C      333
            D      444
            
            
         Permission
         
            url=.....
              title=....
            
        id       url            title
        1     "/users/"         "查看用户"
        2     "/users/add/"     "添加用户"
         3    "/customer/add"    "添加客户"
             
         UserInfor_permission
    
            id
            user_id
            permission_id        
             
             
            id    user_id   permission_id
             1       1           1        
             2       1           2
             3       2           2
             
             4       3           1
             5       3           2
             6       3           3
             
             4       4           1
             5       4           2
             6       4          3
             
             
             4       5           1
             5       5           2
             6       5           3
             
             
             4       6           1
             5       6           2
             6       6           3
             
             
             4       7           1
             5       7           2
             6       7           3
        示例:登录人:egon
              访问url:http://127.0.0.1:8000/users/    
             
              
              def users(request):
                 
                 user_id=request.session.get("user_id")
                 
                 
                 obj=UserInfor.objects.filter(pk=user_id).first()
                 obj.permission.all().valuelist("url")
                 
                 
                 
                 return HttpResponse("users.....")
             

    3、版本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) 
         
         

    2、代码实现

    1)项目目录结构

    2)数据库表

    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)
    
        def __str__(self):
            return self.title

     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)

     3、登录验证

    1、session中注册用户,权限

    1.在session中注册用户ID
    request.session['user_id'] = user.pk

    2.初始化 permission_list 并注册到session 中
    initial_session(user,request)


    注意点:

    permission = user.roles.all().values('permission__url').distinct()
    1.values:      
    temp = []
    for role in user.roles.all(): # < QuerySet[ < Role: 保洁 >, < Role: 销售 >] >
    temp.append({
    'title':role.title
    'permission__url': role.permission__url.all()
    })
    return temp

    2.values 不会去重!!
    <QuerySet [{'title': '保洁', 'permission__url': '/users/'},
    {'title': '销售', 'permission__url': '/users/'},
    {'title': '销售', 'permission__url': '/users/add'}]>

    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如何构造?抄袭

     

    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、admin如何验证:302重定向 

     

    3、构建中间件

     

    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/11 0011 9:04
    # @Author  : Venicid
    
    import re
    
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse, redirect
    
    
    class ValidPermission(MiddlewareMixin):
        def process_request(self, request):
    
            # 当前访问路径
            current_path = request.path_info
    
            # 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 None
    
    
            # 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:
                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

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

     5、注意点

    注意点:

    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
                    

  • 相关阅读:
    大脑不清醒什么原因?
    时间同步linux和window
    NTP服务及时间同步(CentOS6.x)
    刚刚我差点被银行信用卡分期给骗了!
    信用卡分期推销太烦人?你可以这样破解
    为何打印机里有一个文档一直等待打印,删不掉?
    win7下如何显示缅文和使用缅文输入法?
    win7如何连接蓝牙键盘
    @Autowired @Transaction @Service同时出现。
    Eclipse中设置格式化jsp自动换行
  • 原文地址:https://www.cnblogs.com/venicid/p/9458776.html
Copyright © 2011-2022 走看看