Django的权限管理

一:功能分析:

一个成熟的web应用,对权限的控制、管理是不可少的;对于一个web应用来说是什么权限?

这要从web应用的使用说起,用户在浏览器输入一个url,访问server端,server端返回这个url下对应的资源;

所以 对于用户来说 1个可以访问url 就等于1个权限 

为什么某些网站会为广大用户做角色划分呢(比如 普通、会员、黑金、白金)?

因为给用户归类后,便于权限的划分、控制、管理;

所以我们把这种基于角色来做得权限控制,称为RBAC(Role Basic Access Control)

二:权限管理数据库表结构设计:

1, 用户表: 用户表和角色表为多对多关系, 1个用户可以有多个角色, 1个角色可以被多个用户划分;

2, 角色表: 角色和权限也是多对多关系, 一个角色可以有多个权限,以恶搞权限可以划分给多个角色

3,菜单表: 由于在前段引导用户找到自己的权限,并可以设置多级菜单对用户权限进行划分;所以权限表和菜单表是1对多关系;

总结: 一般设计包含层级结构嵌套,且嵌套的层级无法预测的表结构使用自关联;(因为无法预测表结构的深度)

三:权限组件录入数据

1, 新建一个django项目

rbac-基于角色的权限控制

2, 增加一个app应用

3, 什么事rbac??

项目与应用的关系

  一个项目包含多个应用

  一个应用可以包含在多个项目中

  基于角色的权限访问控制(Role-Base Access Control)

 

生成表

4, rbac --》 models.py

3张表,会生成5张表

from django.db import models


class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32, default=123)
    email = models.EmailField()
    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):
    url = models.CharField(max_length=32)
    title = models.CharField(max_length=32)

    def __str__(self):
        return self.title
生成数据

5,数据库迁移

6,查看表,发现没有自己写的表???

7, settins配置

8,入口文件

9, 再次执行数据迁移命令,查看表

 

admin添加数据

10,添加数据: admin

11, 创建管理员,用户名,密码

12, 登入admin

13,默认没有我们自己写的app里面的表,需要注册才会现实表

14,第三张表不用加。

15

16,添加用户,会自动pop角色表 pop权限表 ---》 先增加一个权限

17,查看权限表字段,目前只显示1列,设置为两个字段!!

18, 自定义显示的字段

展示列

19,角色关系

 

 

四:获取登入用户的所有权限

1,url.py

2,登陆代码

views.py

from django.shortcuts import render, redirect
from rbac.models import *


# Create your views here.
def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    else:
        user = request.POST.get("username")
        pwd = request.POST.get("password")
        user = UserInfo.objects.filter(name=user, pwd=pwd).first()
        if user:
            pass
        else:
            return redirect("/login/")
View Code

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <div>
        user
        <input type="text" name="username">
    </div>
    <div>
        password
        <input type="text" name="password">
    </div>
    <div>
        <button>login</button>
    </div>

</form>
</body>
</html>
View Code

3, 登陆成功之后做什么???

session

4,登入成功可以写session值,下次查看别的页面就知道是谁了

pk指的是主键

5,查看django_session表

随机字符串={user_id=3, }通过取当前用户的id--->然后就可以取当前用户的所有信息

 

获取当前用户的所有权限

6,获取当前用户的所有权限

user.roles.all()  找到用户所有角色

a.假设alex登陆成功后,所有的角色title(销售, 销售经理)

 

b.查看销售角色对应的所有权限

title user.roles.all().values("title", "permission", "permission__url", "permission__title")

......

7,权限去重

又重复的权限,应该去重!!!(title只是为了查看角色, 接下来不打印title, 数据就完全相同了。)

user.roles.all().values("permissions__url", "permissions__title").distince()

五:登陆用户权限写入到session中

1,登陆admin,将销售的权限改成智能查看订单列表

2,url.py

3, views.py 这样的情况任何人都能访问

思考问题: 怎么给页面加权限???

将登陆用户权限写入到session中

4,将登陆用户权限列表写入到session里面。

session = {"user_id":1, "permission_list": ["/users/", "/orders/"]}

5,访问用户列表,用户订单的时候,取session里面取值(权限列表)

 判断条件: 只要访问的url在权限列表里面,则可以访问。

6,那么问题来了, 如果url有正则(\d+),怎么判断呢???

 

正则匹配

7, match方法

import re

ret = re.match("/users/edit/(\d+)", "/users/edi123")
print(ret)  # re.match方法: 匹配不上返回None

匹配成功的返回值

8,users

orders 订单也一样的判断

 

中间件

1, 问题: 判断代码写到单独的一个文件中,然后中间件中引入。避免太多的重复

 

2, 应该继承什么呢?

 

3,复制引入文件的代码到rbac.py文件中

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self, request):
        print("123")

4,配置session文件。将自定义的中间件文件配置一下

6,将判断权限的逻辑代码剪切到rbac.py文件中

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, redirect, HttpResponse

class M1(MiddlewareMixin):
    def process_request(self, request):

        current_path = request.path_info

        valid_url_menu = ["/login/", "/reg/", "/admin/.*"]  # 设置的白名单
        import re
        for valid_url in valid_url_menu:
            ret = re.match(valid_url, current_path)
            if ret:
                return None

        permission_list = request.session.get("permission_list")
        if not permission_list:
            return redirect("/login/")

        flag = False
        for permission_url in permission_list:
            ret = re.match(permission_url, current_path)
            if ret:
                flag = True
                break
        if not flag:
            return HttpResponse("没有权限")
中间件代码

 

posted @ 2018-10-08 22:31  猴里吧唧  阅读(441)  评论(1)    收藏  举报