權限咱們應該不陌生,不同的人權限不一樣,咱們常說「官大一級壓死人」,就是說每個職位權限不一樣。咱們常常會碰到說必須是管理員才能操做,這就是管理員的一種權限。什麼是權限呢?總的來講,在咱們項目中,就是一個包含正則表達式的URL就是一個權限。css
咱們簡稱爲RBAC。(url base access control)。html
權限的做用,就是生成一個獨立的組件,咱們想用時均可以用。python
說了這麼多也不必定會用,下面咱們來看一個在Django框架中的實例。jquery
咱們新建一個project_rbac項目,再建兩個app分別爲app01和rbac,app01專門放與項目相關邏輯方面的應用,而rbac專門放與權限相關的。正則表達式
記得在settings.py中配置新建的項目。數據庫
STATIC_URL = '/static/' STATICFILES_DIRS=[ os.path.join(BASE_DIR,"static") ]
rbac.models.pydjango
建三個類,五張表bootstrap
# 用戶表 class UserInfo(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
角色表和權限表是多對多的關係(一個角色能夠有多個權限,一個權限能夠對應多個角色)
用戶表和角色表是多對多的關係(一個用戶能夠有多個角色,一個角色有多個用戶) session
- 先建立一個超級用戶 python3 manage.py createsuperuser - 用戶名 root - 密碼 123456 - 在admin.py 中 from rbac import models admin.site.register(models.Permission) admin.site.register(models.Role) admin.site.register(models.UserInfo) 這樣的話上去的是英文的,若是你想讓中文顯示就在類中加一個類 class Meta: verbose_name_plural = "權限表" - 當你給關聯字段錄入數據的時候會有錯誤提示,那麼在類中你的那個關聯字段在加一個屬性blank = True 能夠爲空 permissions = models.ManyToManyField(to="Permission",verbose_name="具備的全部權限", blank=True)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>登陸</title> {% load static %} <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="{% static "bs/css/bootstrap.css" %}"> <style> .container{ margin-top: 150px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <div class="panel panel-primary"> <div class="panel-heading">登陸頁面</div> <div class="panel-body"> <form action="" method="post"> {% csrf_token %} <div class="form-group"> <label for="user">用戶名</label> <input type="text" class="form-control" id="user" name="user" placeholder="請輸入用戶名"> </div> <div class="form-group"> <label for="pwd">密碼</label> <input type="password" class="form-control" id="pwd" name="pwd" placeholder="請輸入密碼"> </div> <input type="submit" class="btn btn-primary login_btn" value="登陸"> </form> </div> </div> </div> </div> </div> <script src="{% static '/js/jquery-3.2.1.min.js' %}"></script> <script src="{% static '/bs/js/bootstrap.js' %}"></script> </body> </html>
在rbac應用下面新建service包,新建perssions.py.app
def initial_session(user,request): ## 查詢當前登陸用戶的全部權限 permissions = user.roles.all().values("permissions__url").distinct() # 權限列表去重 permission_list = [] for item in permissions: # 循環取到的全部權限 permission_list.append(item["permissions__url"]) # 將該用戶的權限url添加到permission_list列表中 print(permission_list) # 在session中註冊權限列表 request.session["permission_list"] = permission_list
# 登陸 def login(request): if request.method == "POST": user = request.POST.get("user") # 取到輸入的用戶名 pwd = request.POST.get("pwd") # 取到輸入的密碼 user = UserInfo.objects.filter(name=user, pwd=pwd).first() # 判斷該用戶是否存在於數據庫 if user: # 登陸成功 # 在session中註冊用戶ID request.session["user_id"] = user.pk # 查詢當前登陸用戶的全部角色 # user_list= user.roles.all() #角色列表 <QuerySet [<Role: 保潔>, <Role: 銷售>]> # 查詢當前登陸用戶的全部權限 initial_session(user,request) return HttpResponse("登陸成功") return render(request, "login.html")
在rbac應用下面新建service包,新建rbac.py,做爲中間件。
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 '''檢查是否屬於白名單''' valid_url_list = ["/login/", "/reg/", "/admin/.*"] # 白名單列表 for url in valid_url_list: # 查看是否屬於白名單 ret = re.match(url, current_path) # 當前路徑與白名單列表作匹配 if ret: # 當前路徑屬於白名單 return None # 經過這個校驗 '''校驗是否登陸 ''' user_id = request.session.get("user_id") # 取到當前登陸用戶的id值 if not user_id: # 取不到id,說明沒登陸,跳轉到登陸頁面,從新登陸 return redirect("/login/") '''校驗權限''' 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
設置白名單,是指全部人均可以訪問的url。登陸校驗,在訪問某一些url時,只有登陸才能訪問,若是沒登陸,跳轉到登陸頁面。權限校驗,判斷當前登陸用戶有哪些權限,對於沒有該權限的用戶,是無訪問的。