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