rbac - 初識

1、rbac

權限組件
   1 項目與應用
        一個項目,能夠有多個應用
        一個應用,能夠在多個項目下
        前提:應用是組件!!

   2 什麼是權限?
     一個包含正則表達式url就是一個權限

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

     UserInfor
         id
         name
         pwd
         permission=models.manytomany(Permission)  多對多

    id    name   pwd
    1    egon   123
    2    alex   456
    3    A      111
    4    B      222
    5    C      333
    6    D      444


     Permission
        id
        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

         7       4           1
         8       4           2
         9       4           3


         10       5           1
         11       5           2
         12       5           3


         13       6           1
         14       6           2
         15       6           3


         16       7           1
         17       7           2
         18       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.....")


這樣作 是否 有問題?
假設:10人 。。。 應該,不一樣的角色有不一樣的權限!

不要給人定權限,
應該給角色定權限
rbac  正確的 見 版本2
------------------------------------------------------------

    # 版本2:

    UserInfor
         id
         name
         pwd
         roles = manytomany() 多對多

        name   pwd
        egon   123
        alex   456
        alex   456
        alex   456

    Role
       id
       title=.......
       permissions = manytomany() 多對多

         id   title
         1    銷售員

    UserInfor2Role

       id     user_id    role_id
        1        1          1

    Permission
        id
        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


rbac(role-based access control)

app01 作的是項目相關的邏輯內容
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
筆記

rbac(role-based access control)html

基於角色的權限訪問控制 正則表達式

2、數據庫

1.新建一個應用:
startapp rbac

INSTALLED_APPS = [
...
'app01.apps.App01Config',
'rbac.apps.RbacConfig',
]

makemigrations
migrate

models.py數據庫

from django.db import models

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

1.前提
createsuperuser
(yuan yuan1234)

admin.pydjango

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、登陸驗證 (session permission_list)  

1.在session中註冊用戶ID
request.session['user_id'] = user.pk

2.初始化 permission_list 並註冊到session 中
initial_session(user,request)

rbac/service/permission.py
def initial_session(user, request):
    permission = user.roles.all().values('permission__url').distinct()

    # print(permission)
    # 去重後的  全部權限!! 將權限 存在 session 中!!
    # <QuerySet [{'permission__url': '/users/'}, {'permission__url': '/users/add'}]>

    permission_list = []
    for item in permission:
        permission_list.append(item['permission__url'])

    print(permission_list)
    # ['/users/', '/users/add']

    request.session['permission_list'] = permission_list

 

注意點:session

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'}]>

views.py
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中註冊用戶ID
            request.session['user_id'] = user.pk

            # 初始化 permission_list 並註冊到session 中
            initial_session(user,request)

            return HttpResponse('登陸成功')

    return render(request,'login.html')

5、基於中間件的權限校驗

MIDDLEWARE = [
...
'django.middleware.csrf.CsrfViewMiddleware',
...
'rbac.service.rbac.ValidPermission',
]

注意點:app

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('無訪問權限!')

rbac/service/rbac.py
# -*- coding:utf-8 -*-
from django.shortcuts import HttpResponse, render, redirect
from django.utils.deprecation import MiddlewareMixin
import re

class ValidPermission(MiddlewareMixin):

    def process_request(self,request):

        current_path = request.path_info

        # 白名單,不須要任何權限的url
        valid_url_list = ['/login/', '/reg/', '/admin/.*']

        for valid_url in valid_url_list:
            ret = re.match(valid_url, current_path)
            if ret:
                return

        # 校驗是否登陸
        user_id = request.session.get('user_id')
        if not user_id:
            return redirect('/login/')

        # 校驗權限
        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('無訪問權限!')
相關文章
相關標籤/搜索