RBAC(Role-Based Access Control,基於角色的訪問控制),就是用戶經過角色與權限進行關聯。簡單地說,一個用戶擁有若干角色,一個角色擁有若干權限。這樣,就構形成「用戶-角色-權限」的受權模型。在這種模型中,用戶與角色之間,角色與權限之間都是多對多的關係。css
一個可訪問的含正則表達式的url就是一個權限,利用角色控制訪問url。html
用戶組,角色,權限正則表達式
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("Role") def __str__(self): return self.name class Role(models.Model): title=models.CharField(max_length=32) permissions=models.ManyToManyField("Permission") def __str__(self): return self.title class Permission(models.Model): url=models.CharField(max_length=32) title=models.CharField(max_length=32,default="") p_group=models.ForeignKey("PermissionGroup",default=1) code=models.CharField(max_length=32,default="list",) def __str__(self): return self.title class PermissionGroup(models.Model): name=models.CharField(max_length=32) def __str__(self): return self.name
將登陸用戶的全部權限信息注入到session中數據庫
rbac/service/initail.pydjango
def permission_session(user,request): # 將當前user的全部權限注入session中 # 方式1: #permissions = user.roles.all().values("permissions__url").distinct() # permission_list = [] # for i in permissions: # permission_list.append(i.get("permissions__url")) # # request.session["permission_list"] = permission_list # 方式2: permissions = user.roles.all().values("permissions__url","permissions__p_group_id","permissions__code").distinct() # print(permissions) permission_dict={} for permission in permissions: p_group_id=permission.get("permissions__p_group_id") if p_group_id in permission_dict: permission_dict[p_group_id]["urls"].append(permission.get("permissions__url")) permission_dict[p_group_id]["codes"].append(permission.get("permissions__code")) else: permission_dict[p_group_id]={ "urls":[permission.get("permissions__url")], "codes":[permission.get("permissions__code")],} print(permission_dict) request.session["permission_dict"]=permission_dict
功能: 1.白名單驗證;bootstrap
2.驗證是否已經寫入session,即:是否已經登陸;session
3.當前訪問的url與當前用戶的權限url進行匹配驗證,並在request中寫入code信息app
settings.py數據庫設計
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', "rbac.service.rbac.PermissionValid", ]
rabc.pyide
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse,redirect,render class PermissionValid(MiddlewareMixin): def process_request(self,request): valid_url=["/login/","/reg/","/admin/.*"] #白名單 import re for url in valid_url: url="^%s$"%url ret=re.match(url,request.path_info) if ret: return None #.驗證是否已經寫入session,即:是否已經登陸 if not request.session.get("user_id"): return redirect("/login/") current_path = request.path_info # 方式1: # permission_list = request.session.get("permission_list") # # import re # # 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("無權訪問") # 方式2: #與當前訪問的url與權限url進行匹配驗證,並在request中寫入code信息, permission_dict = request.session.get("permission_dict") import re flag = False for item in permission_dict.values(): urls=item["urls"] for permission in urls: permission="^%s$"%permission ret = re.match(permission, current_path) if ret: print("codes",item.get("codes")) request.codes=item.get("codes") return None return HttpResponse("無權訪問")
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from rbac.models import * class PermissionCode(object): def __init__(self,codes): self.codes=codes def list(self): return "list" in self.codes def add(self): return "add" in self.codes def edit(self): return "edit" in self.codes def delete(self): return "del" in self.codes def users(request): user_list=User.objects.all() per=PermissionCode(request.codes) return render(request,"users.html",locals()) def add_users(request): return HttpResponse("添加用戶") def change_users(request,id): return HttpResponse("編輯用戶") def delete_users(request,id): return HttpResponse("刪除用戶") 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: request.session["user_id"]=user.pk from rbac.service.initail import permission_session permission_session(user,request) return HttpResponse("登陸成功") return render(request,"login.html")
def permission_session(user,request): # 將當前user的全部權限注入session中 # 方式1: #permissions = user.roles.all().values("permissions__url").distinct() # permission_list = [] # for i in permissions: # permission_list.append(i.get("permissions__url")) # # request.session["permission_list"] = permission_list # 方式2: permissions = user.roles.all().values("permissions__url","permissions__p_group_id","permissions__code").distinct() # print(permissions) permission_dict={} for permission in permissions: p_group_id=permission.get("permissions__p_group_id") if p_group_id in permission_dict: permission_dict[p_group_id]["urls"].append(permission.get("permissions__url")) permission_dict[p_group_id]["codes"].append(permission.get("permissions__code")) else: permission_dict[p_group_id]={ "urls":[permission.get("permissions__url")], "codes":[permission.get("permissions__code")],} print(permission_dict) request.session["permission_dict"]=permission_dict
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse,redirect,render class PermissionValid(MiddlewareMixin): def process_request(self,request): valid_url=["/login/","/reg/","/admin/.*"] #白名單 import re for url in valid_url: url="^%s$"%url ret=re.match(url,request.path_info) if ret: return None #.驗證是否已經寫入session,即:是否已經登陸 if not request.session.get("user_id"): return redirect("/login/") current_path = request.path_info # 方式1: # permission_list = request.session.get("permission_list") # # import re # # 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("無權訪問") # 方式2: #與當前訪問的url與權限url進行匹配驗證,並在request中寫入code信息, permission_dict = request.session.get("permission_dict") import re flag = False for item in permission_dict.values(): urls=item["urls"] for permission in urls: permission="^%s$"%permission ret = re.match(permission, current_path) if ret: print("codes",item.get("codes")) request.codes=item.get("codes") return None return HttpResponse("無權訪問")
from django.contrib import admin # Register your models here. from .models import * admin.site.register(User) admin.site.register(Role) class PermissionConfig(admin.ModelAdmin): list_display = ["title","url","p_group","code"] admin.site.register(Permission,PermissionConfig) admin.site.register(PermissionGroup)
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("Role") def __str__(self): return self.name class Role(models.Model): title=models.CharField(max_length=32) permissions=models.ManyToManyField("Permission") def __str__(self): return self.title class Permission(models.Model): url=models.CharField(max_length=32) title=models.CharField(max_length=32,default="") p_group=models.ForeignKey("PermissionGroup",default=1) code=models.CharField(max_length=32,default="list",) def __str__(self): return self.title class PermissionGroup(models.Model): name=models.CharField(max_length=32) def __str__(self): return self.name
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', "rbac.apps.RbacConfig", ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', "rbac.service.rbac.PermissionValid", ]
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/$', views.login), url(r'^users/$', views.users), url(r'^users/add/$', views.add_users), url(r'^users/(\d+)/change/$', views.change_users), url(r'^users/(\d+)/delete/$', views.delete_users), ]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用戶名:<input type="text" name="user"> 密碼:<input type="text" name="pwd"> <input type="submit"> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <div class="container"> <h3>查看用戶</h3> <div class="col-md-6"> {% if per.add %} <a href="/users/add/" class="btn btn-primary">添加用戶</a> {% endif %} <table class="table table-borderd table-striped col-md-offset-4"> {% for user in user_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ user.name }}</td> {% if per.edit %} <td><a href="/users/{{ user.pk }}/change" class="btn btn-success">編輯</a></td> {% endif %} {% if per.delete %} <td><a href="/users/{{ user.pk }}/delete/" class="btn btn-success">刪除</a></td> {% endif %} </tr> {% endfor %} </table> </div> </div> </body> </html>