当前位置: 首页 > news >正文

django-权限管理

 

django-权限管理

第一步
1196552-20171125150849968-532187780.png

#创建表

from django.db import models

class Permission(models.Model):
    """
    权限表
    """
    title = models.CharField(verbose_name='标题',max_length=32)
    url = models.CharField(verbose_name="含正则URL",max_length=64)
    is_menu = models.BooleanField(verbose_name="是否是菜单")
    class Meta:
        verbose_name_plural = "权限表"               #添加表到后台中去

    def __str__(self):
        return self.title

class User(models.Model):
    """
    用户表
    """
    username = models.CharField(verbose_name='用户名',max_length=32)         #verbose_name将在后台页面上显示自定义的名字
    password = models.CharField(verbose_name='密码',max_length=64)
    email = models.CharField(verbose_name='邮箱',max_length=32)
    roles = models.ManyToManyField(verbose_name='具有的所有角色',to="Role",blank=True)
    class Meta:
        verbose_name_plural = "用户表"                            #添加用户表到后台中去

    def __str__(self):
        return self.username

class Role(models.Model):
    """
    角色表
    """
    title = models.CharField(max_length=32)
    permissions = models.ManyToManyField(verbose_name='具有的所有权限',to='Permission',blank=True)    #blank=True的作用是关联的角色可以为空
    class Meta:
        verbose_name_plural = "角色表"                         #添加角色表到后台中去

    def __str__(self):
        return self.title






-
x
1
#创建表
2

          
3
from django.db import models
4

          
5
class Permission(models.Model):
6
    """
7
    权限表
8
    """
9
    title = models.CharField(verbose_name='标题',max_length=32)
10
    url = models.CharField(verbose_name="含正则URL",max_length=64)
11
    is_menu = models.BooleanField(verbose_name="是否是菜单")
12
    class Meta:
13
        verbose_name_plural = "权限表"               #添加表到后台中去
14

          
15
    def __str__(self):
16
        return self.title
17

          
18
class User(models.Model):
19
    """
20
    用户表
21
    """
22
    username = models.CharField(verbose_name='用户名',max_length=32)         #verbose_name将在后台页面上显示自定义的名字
23
    password = models.CharField(verbose_name='密码',max_length=64)
24
    email = models.CharField(verbose_name='邮箱',max_length=32)
25
    roles = models.ManyToManyField(verbose_name='具有的所有角色',to="Role",blank=True)
26
    class Meta:
27
        verbose_name_plural = "用户表"                            #添加用户表到后台中去
28

          
29
    def __str__(self):
30
        return self.username
31

          
32
class Role(models.Model):
33
    """
34
    角色表
35
    """
36
    title = models.CharField(max_length=32)
37
    permissions = models.ManyToManyField(verbose_name='具有的所有权限',to='Permission',blank=True)    #blank=True的作用是关联的角色可以为空
38
    class Meta:
39
        verbose_name_plural = "角色表"                         #添加角色表到后台中去
40

          
41
    def __str__(self):
42
        return self.title
43

          
44

          
45

          
46

          
47

          
48

          
49

          
第二步
根据django自己的admin来登陆
from django.conf.urls import url
from django.contrib import admin
from rbac import views
from app01 import views as app01_views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
xxxxxxxxxx
7
 
1
from django.conf.urls import url
2
from django.contrib import admin
3
from rbac import views
4
from app01 import views as app01_views
5
urlpatterns = [
6
    url(r'^admin/', admin.site.urls),
7
]
在项目目录里创建登陆用户名和密码
 
#创建用户名和密码
python manage.py createsuperuser      
xxxxxxxxxx
3
 
1
#创建用户名和密码
2
python manage.py createsuperuser      
3

          
1196552-20171125150853437-118501782.png
 然后进行登陆输入你自己创建的用户名和密码
1196552-20171125150853718-833103252.png
 登陆进去,那么怎么显示你的表呢
#在admin.py里导入
        from django.contrib import admin
        from . import models             
        admin.site.register(models.Permission)                           
        admin.site.register(models.User)
        admin.site.register(models.Role)
xxxxxxxxxx
6
 
1
#在admin.py里导入
2
        from django.contrib import admin
3
        from . import models             
4
        admin.site.register(models.Permission)                           
5
        admin.site.register(models.User)
6
        admin.site.register(models.Role)
1196552-20171125150854031-494062318.png
 运行结果
1196552-20171125150854453-1312538457.png
 可以看到默认是数据库的表名一一对应的,还可以更改名字
 class Role(models.Model):
    """
    角色表
    """
    title = models.CharField(max_length=32)
    permissions = models.ManyToManyField(verbose_name='具有的所有权限',to='Permission',blank=True)
    class Meta:
        verbose_name_plural = "角色表"

    def __str__(self):
        return self.title
   
    class Meta:                                           #添加 Meta
        verbose_name_plural = "角色表"                    #更改名字
xxxxxxxxxx
14
 
1
 class Role(models.Model):
2
    """
3
    角色表
4
    """
5
    title = models.CharField(max_length=32)
6
    permissions = models.ManyToManyField(verbose_name='具有的所有权限',to='Permission',blank=True)
7
    class Meta:
8
        verbose_name_plural = "角色表"
9

          
10
    def __str__(self):
11
        return self.title
12
   
13
    class Meta:                                           #添加 Meta
14
        verbose_name_plural = "角色表"                    #更改名字
输出结果:
1196552-20171125150854750-1949467854.png
 
第三步
用户登录程序
    - 获取当前用户具有的所有权限(去重)
     - 获取权限中的url,放置到session中
初始化权限信息,获取权限信息并放置到session中
import re

from django.shortcuts import render,redirect,HttpResponse
from rbac import models
from rbac.service.init_permission import init_permission                             #导入自己写的初始化的模块
def login(request):
    if request.method == "GET":
        return render(request,'login.html')
    else:
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        user = models.User.objects.filter(username=user,password=pwd).first()          #首先先查到用户输入的user字段存不存在找到用户输入的字段
        print(request.POST)                
        if not user:                                                                     #判断用户在不在
            return render(request, 'login.html')                                          #如果不在则返回login页面
        init_permission(user,request)                                                     #把user的对象和接收的用户信息传过去
        return redirect('/index/')                       


def index(request):

    return HttpResponse('欢迎登录')


def userinfo(request):
    return HttpResponse('用户列表页面')


def userinfo_add(request):
    return HttpResponse('添加用户页面')

def order(request):
    return HttpResponse('订单列表页面')

def order_add(request):
    return HttpResponse('添加订单页面')
x
 
1
import re
2

          
3
from django.shortcuts import render,redirect,HttpResponse
4
from rbac import models
5
from rbac.service.init_permission import init_permission                             #导入自己写的初始化的模块
6
def login(request):
7
    if request.method == "GET":
8
        return render(request,'login.html')
9
    else:
10
        user = request.POST.get('user')
11
        pwd = request.POST.get('pwd')
12
        user = models.User.objects.filter(username=user,password=pwd).first()          #首先先查到用户输入的user字段存不存在找到用户输入的字段
13
        print(request.POST)                
14
        if not user:                                                                     #判断用户在不在
15
            return render(request, 'login.html')                                          #如果不在则返回login页面
16
        init_permission(user,request)                                                     #把user的对象和接收的用户信息传过去
17
        return redirect('/index/')                       
18

          
19

          
20
def index(request):
21

          
22
    return HttpResponse('欢迎登录')
23

          
24

          
25
def userinfo(request):
26
    return HttpResponse('用户列表页面')
27

          
28

          
29
def userinfo_add(request):
30
    return HttpResponse('添加用户页面')
31

          
32
def order(request):
33
    return HttpResponse('订单列表页面')
34

          
35
def order_add(request):
36
    return HttpResponse('添加订单页面')
def init_permission(user,request):                                           #这里接受了视图函数传过来的user querset对象和request用户的信息
    """
    初始化权限信息,获取权限信息并放置到session中。
    :param user:
    :param request:
    :return:
    """
    permission_list = user.roles.values('permissions__title', 'permissions__url', 'permissions__is_menu').distinct()            #   通过user的对象正向查询向下滑线查询拿到title,url,is_menu字段并进行去重
    url_list = []                                                                                                            #定义一个空字典
    for item in permission_list:                                                                                   #循环permission_list所有的值
        url_list.append(item['permissions__url'])                                                                  #把url的字段的内容放入定义的空字典中
    print(url_list)                         
    request.session['permission_url_list'] = url_list                                                              #通过这里通过了说明这个用户名是存在的把所有的url字段权限的信息加入到session中
x
 
1
def init_permission(user,request):                                           #这里接受了视图函数传过来的user querset对象和request用户的信息
2
    """
3
    初始化权限信息,获取权限信息并放置到session中。
4
    :param user:
5
    :param request:
6
    :return:
7
    """
8
    permission_list = user.roles.values('permissions__title', 'permissions__url', 'permissions__is_menu').distinct()            #   通过user的对象正向查询向下滑线查询拿到title,url,is_menu字段并进行去重
9
    url_list = []                                                                                                            #定义一个空字典
10
    for item in permission_list:                                                                                   #循环permission_list所有的值
11
        url_list.append(item['permissions__url'])                                                                  #把url的字段的内容放入定义的空字典中
12
    print(url_list)                         
13
    request.session['permission_url_list'] = url_list                                                              #通过这里通过了说明这个用户名是存在的把所有的url字段权限的信息加入到session中
14

          
1196552-20171125150855359-1215174801.png
 
第四步 
在通过中间件来进行权限的管理
想要进行权限控制需要login和后台的admin路径对外开放,然后用户能够通过登陆来进行权限的验证,不然就会陷入死循环
白名单:
#自定制的
# ######################### rbac ############################
#白名单
VALID_URL = [
    "/login/",
    "/admin.*"
]
xxxxxxxxxx
7
 
1
#自定制的
2
# ######################### rbac ############################
3
#白名单
4
VALID_URL = [
5
    "/login/",
6
    "/admin.*"
7
]
1196552-20171125150855718-1179776211.png
 



import re

from django.shortcuts import redirect,HttpResponse
from django.conf import settings                                                #settings是django特有的 在settings中都可以通过django.conf来调用,

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response


class RbacMiddleware(MiddlewareMixin):

    def process_request(self,request):                      
        # 1. 获取当前请求的URL
        # request.path_info
        # 2. 获取Session中保存当前用户的权限
        # request.session.get("permission_url_list')
        current_url = request.path_info                             #获取到用户输入的Url地址

        # 当前请求不需要执行权限验证
        for url in settings.VALID_URL:                             #拿到白名单 进行for循环验证因为白名单是一个列表的形式如果用户输入的url存在于白名单之中的
            if re.match(url,current_url):                          #用循环取出的白名单与用户输入的url路径进行re正则判断,判断成功则有值,没有成功则没有值
                return None                                        #成功return None 则继续运行后面的中间件和视图函数

        permission_list = request.session.get("permission_url_list")       #通过request,get session中的值,如果没有则为空
        if not permission_list:                                           #进行判断
            return redirect('/login/')                                    #没有的话则重定向login登陆页面中
           #如果有的话则继续执行下面代码
        flag = False                                                     
        for db_url in permission_list:                               #有值则循环取值
            regax = "^{0}$".format(db_url)                           #把循环的值通过.format按索引值穿参进行字符串拼接    注:如果不进行字符串的拼接加上^$的话,匹配的值只要一个正确后面的就不管了,比如addteacher/   addteacher/add/1这样的也能匹配成功,所以通过^$以..开头和以..结尾能够进行精确的匹配   
            if re.match(regax, current_url):                          #进行re正则匹配这样就能精确的匹配了,
                flag = True                                           #正则匹配成功的话flag=True
                break                                                 #匹配成功了直接就退出循环了

        if not flag:                                                  #用户的权限不匹配的话,则进行not false 就是true表示成功则往下执行
            return HttpResponse('无权访问')                            #直接返回无权访问
x
1
import re
2

          
3
from django.shortcuts import redirect,HttpResponse
4
from django.conf import settings                                                #settings是django特有的 在settings中都可以通过django.conf来调用,
5

          
6
class MiddlewareMixin(object):
7
    def __init__(self, get_response=None):
8
        self.get_response = get_response
9
        super(MiddlewareMixin, self).__init__()
10

          
11
    def __call__(self, request):
12
        response = None
13
        if hasattr(self, 'process_request'):
14
            response = self.process_request(request)
15
        if not response:
16
            response = self.get_response(request)
17
        if hasattr(self, 'process_response'):
18
            response = self.process_response(request, response)
19
        return response
20

          
21

          
22
class RbacMiddleware(MiddlewareMixin):
23

          
24
    def process_request(self,request):                      
25
        # 1. 获取当前请求的URL
26
        # request.path_info
27
        # 2. 获取Session中保存当前用户的权限
28
        # request.session.get("permission_url_list')
29
        current_url = request.path_info                             #获取到用户输入的Url地址
30

          
31
        # 当前请求不需要执行权限验证
32
        for url in settings.VALID_URL:                             #拿到白名单 进行for循环验证因为白名单是一个列表的形式如果用户输入的url存在于白名单之中的
33
            if re.match(url,current_url):                          #用循环取出的白名单与用户输入的url路径进行re正则判断,判断成功则有值,没有成功则没有值
34
                return None                                        #成功return None 则继续运行后面的中间件和视图函数
35

          
36
        permission_list = request.session.get("permission_url_list")       #通过request,get session中的值,如果没有则为空
37
        if not permission_list:                                           #进行判断
38
            return redirect('/login/')                                    #没有的话则重定向login登陆页面中
39
           #如果有的话则继续执行下面代码
40
        flag = False                                                     
41
        for db_url in permission_list:                               #有值则循环取值
42
            regax = "^{0}$".format(db_url)                           #把循环的值通过.format按索引值穿参进行字符串拼接    注:如果不进行字符串的拼接加上^$的话,匹配的值只要一个正确后面的就不管了,比如addteacher/   addteacher/add/1这样的也能匹配成功,所以通过^$以..开头和以..结尾能够进行精确的匹配   
43
            if re.match(regax, current_url):                          #进行re正则匹配这样就能精确的匹配了,
44
                flag = True                                           #正则匹配成功的话flag=True
45
                break                                                 #匹配成功了直接就退出循环了
46

          
47
        if not flag:                                                  #用户的权限不匹配的话,则进行not false 就是true表示成功则往下执行
48
            return HttpResponse('无权访问')                            #直接返回无权访问
49

          
权限管理流程图
1196552-20171125150856140-1329166188.png
 































来自为知笔记(Wiz)


转载于:https://www.cnblogs.com/zcfx/p/7895348.html

相关文章:

  • [转]OOA/OOD/OOP区别
  • 绝对常用的Linux命令
  • 【HeadFirst 设计模式学习笔记】3 装饰模式
  • Windows Phone 7 学习笔记2:感应设备的方向
  • ssh 断开处理
  • 关于JavaScript 的事件[下]
  • table-layout
  • 双系统引导故障排除
  • python 守护进程(daemon)
  • Gradle与Makefile构建工具的对比
  • 如何读取Access里的OLE类型的图片
  • 让全世界的中小企业都可以用上的全方位上网行为管理系统。
  • 20171127-构建之法:现代软件工程-阅读笔记
  • Mysql实现企业级主从复制和互为主从模式架构
  • topcoder srm 495 div1
  • Google 是如何开发 Web 框架的
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • DOM的那些事
  • es6--symbol
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • JavaScript服务器推送技术之 WebSocket
  • Java知识点总结(JavaIO-打印流)
  • JS题目及答案整理
  • rc-form之最单纯情况
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Shadow DOM 内部构造及如何构建独立组件
  • ubuntu 下nginx安装 并支持https协议
  • vue-loader 源码解析系列之 selector
  • 记一次和乔布斯合作最难忘的经历
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 容器服务kubernetes弹性伸缩高级用法
  • 深度学习中的信息论知识详解
  • 我有几个粽子,和一个故事
  • HanLP分词命名实体提取详解
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​渐进式Web应用PWA的未来
  • (003)SlickEdit Unity的补全
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (二)WCF的Binding模型
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • **python多态
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET企业级应用架构设计系列之结尾篇
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .NET使用存储过程实现对数据库的增删改查
  • .project文件
  • @GetMapping和@RequestMapping的区别
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)
  • [ 蓝桥杯Web真题 ]-布局切换
  • [20170705]diff比较执行结果的内容.txt
  • [2544]最短路 (两种算法)(HDU)