權限管理具體代碼實現


1、settings

  1 """
  2 Django settings for day80 project.
  3 
  4 Generated by 'django-admin startproject' using Django 1.11.6.
  5 
  6 For more information on this file, see
  7 https://docs.djangoproject.com/en/1.11/topics/settings/
  8 
  9 For the full list of settings and their values, see
 10 https://docs.djangoproject.com/en/1.11/ref/settings/
 11 """
 12 
 13 import os
 14 
 15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 17 
 18 
 19 # Quick-start development settings - unsuitable for production
 20 # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
 21 
 22 # SECURITY WARNING: keep the secret key used in production secret!
 23 SECRET_KEY = '7x(f$0j0c#)hn)8i(uv6j*sg^h_7v9$eak#pu_n4ji05=v28ca'
 24 
 25 # SECURITY WARNING: don't run with debug turned on in production!
 26 DEBUG = True
 27 
 28 ALLOWED_HOSTS = []
 29 
 30 
 31 # Application definition
 32 
 33 INSTALLED_APPS = [
 34     'django.contrib.admin',
 35     'django.contrib.auth',
 36     'django.contrib.contenttypes',
 37     'django.contrib.sessions',
 38     'django.contrib.messages',
 39     'django.contrib.staticfiles',
 40     'app01.apps.App01Config',
 41     'rbac',
 42 ]
 43 from django.middleware.common import CommonMiddleware
 44 MIDDLEWARE = [
 45     'django.middleware.security.SecurityMiddleware',
 46     'django.contrib.sessions.middleware.SessionMiddleware',
 47     'django.middleware.common.CommonMiddleware',
 48     'django.middleware.csrf.CsrfViewMiddleware',
 49     'django.contrib.auth.middleware.AuthenticationMiddleware',
 50     'django.contrib.messages.middleware.MessageMiddleware',
 51     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 52     'rbac.middlewear.rbac.Middle',
 53 ]
 54 
 55 ROOT_URLCONF = 'day80.urls'
 56 
 57 TEMPLATES = [
 58     {
 59         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 60         'DIRS': [os.path.join(BASE_DIR, 'templates')]
 61         ,
 62         'APP_DIRS': True,
 63         'OPTIONS': {
 64             'context_processors': [
 65                 'django.template.context_processors.debug',
 66                 'django.template.context_processors.request',
 67                 'django.contrib.auth.context_processors.auth',
 68                 'django.contrib.messages.context_processors.messages',
 69             ],
 70         },
 71     },
 72 ]
 73 
 74 WSGI_APPLICATION = 'day80.wsgi.application'
 75 
 76 
 77 # Database
 78 # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
 79 
 80 DATABASES = {
 81     'default': {
 82         'ENGINE': 'django.db.backends.sqlite3',
 83         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 84     }
 85 }
 86 
 87 
 88 # Password validation
 89 # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
 90 
 91 AUTH_PASSWORD_VALIDATORS = [
 92     {
 93         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
 94     },
 95     {
 96         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
 97     },
 98     {
 99         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
100     },
101     {
102         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
103     },
104 ]
105 
106 
107 # Internationalization
108 # https://docs.djangoproject.com/en/1.11/topics/i18n/
109 
110 LANGUAGE_CODE = 'en-us'
111 
112 TIME_ZONE = 'UTC'
113 
114 USE_I18N = True
115 
116 USE_L10N = True
117 
118 USE_TZ = True
119 
120 
121 # Static files (CSS, JavaScript, Images)
122 # https://docs.djangoproject.com/en/1.11/howto/static-files/
123 
124 STATIC_URL = '/static/'
125 # ==========靜態文件配置=========
126 STATICFILES_DIRS = (
127     os.path.join(BASE_DIR,'static'),
128 )
129 # ==========rbac============
130 PERMISSION_URL_DICT = "permission_url_list"
131 PERMISSION_MENU_KEY = "permission_menu_list"
132 
133 # =========白名單(不需要權限就可以看到的)==========
134 WHITE_LIST =[
135      "/login/",
136      "/admin.*",
137      "/index/",
138 ]
settings.py

2、rbac應用下的models

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class Role(models.Model):
 5     title = models.CharField(max_length=32,verbose_name="角色")
 6     permissions = models.ManyToManyField(to="Permission",verbose_name="擁有權限的角色",blank=True)  #權限和角色是多對多的關系
 7 
 8     def __str__(self):
 9         return self.title
10     class Meta:
11         verbose_name_plural = "角色表"
12 
13 class Permission(models.Model):
14     title = models.CharField(max_length=32,verbose_name="權限名")
15     url = models.CharField(max_length=32,verbose_name="帶正則的url")
16     codes = models.CharField(max_length=32,verbose_name="代碼")
17     group = models.ForeignKey(to="Group",verbose_name="所屬組",blank=True)  #組和權限是一對多的關系,一個組有多個權限
18     menu_gp = models.ForeignKey(to='Permission',related_name='aaa',null=True,blank=True,verbose_name="組內菜單")
19     def __str__(self):
20         return self.title
21     class Meta:
22         verbose_name_plural = "權限表"
23 
24 class UserInfo(models.Model):
25     name = models.CharField(max_length=32,verbose_name="姓名")
26     password = models.CharField(max_length=64,verbose_name="密碼")
27     email = models.CharField(max_length=32,verbose_name="郵箱")
28     roles = models.ManyToManyField(to="Role",blank=True)  #用戶和角色是多對多的關系
29     def __str__(self):
30         return self.name
31     class Meta:
32         verbose_name_plural = "用戶表"
33 
34 class Group(models.Model):
35     title = models.CharField(max_length=32,verbose_name="組名稱")
36     menu = models.ForeignKey(to="Menu",verbose_name="組內菜單",blank=True)  #一個組下有多個菜單
37     def __str__(self):
38         return self.title
39     class Meta:
40         verbose_name_plural = ""
41 
42 class Menu(models.Model):
43     caption = models.CharField(max_length=32,verbose_name="菜單")
44     def __str__(self):
45         return self.caption
46     class Meta:
47         verbose_name_plural = "菜單表"
models.py

3、urls

 1 from django.conf.urls import url
 2 from django.contrib import admin
 3 from app01 import views
 4 urlpatterns = [
 5     url(r'^admin/', admin.site.urls),
 6     url(r'^login/$', views.login),
 7     url(r'^index/$', views.index),
 8     url(r'^userinfo/$', views.userinfo),
 9     url(r'^userinfo/add/$', views.userinfo_add),
10     url(r'^userinfo/del/(\d+)/$', views.userinfo_del),
11     url(r'^userinfo/edit/(\d+)/$', views.userinfo_edit),
12     url(r'^order/$', views.order),
13     url(r'^order/add/$', views.order_add),
14     url(r'^order/del/(\d+)/$', views.order_del),
15     url(r'^order/edit/(\d+)/$', views.order_edit),
16 ]
urls.py

4、初始化   server--init_permission

 1 #!usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from django.conf import settings
 4 def init_permission(user, request):
 5     '''
 6     初始化權限信息,獲取權限信息並放置到session中
 7     :param user:
 8     :param request:
 9     :return:
10     '''
11     permission_list = user.roles.values('permissions__id',
12                                         'permissions__title',  # 用戶列表
13                                         'permissions__url',
14                                         'permissions__codes',
15                                         'permissions__menu_gp_id',  # 組內菜單ID,Null表示是菜單
16                                         'permissions__group_id',
17                                         'permissions__group__menu_id',  # 菜單ID
18                                         'permissions__group__menu__caption',  # 菜單名稱
19                                         ).distinct()  # 獲取當前角色對象的所有的權限並去重
20     # print(permission_list)
21     # 權限相關
22     url_dict = {}
23     for item in permission_list:
24         group_id = item["permissions__group_id"]
25         url = item["permissions__url"]
26         code = item["permissions__codes"]
27         # print("code_list", code)
28         if group_id in url_dict:
29             url_dict[group_id]["code"].append(code)  # 如果id在里面就把code和url添加進去
30             url_dict[group_id]["urls"].append(url)
31         else:
32             # 如果不在就設置
33             url_dict[group_id] = {
34                 "code": [code, ],
35                 "urls": [url, ]
36             }
37     request.session[settings.PERMISSION_URL_DICT] = url_dict
38     print(url_dict)
39 
40 
41     #菜單相關
42     # 1、先去掉不是菜單的
43     menu_list = []
44     for item in permission_list:
45         tpl = {
46             "id":item["permissions__id"],
47             "title":item["permissions__title"],
48             "url":item["permissions__url"],
49             "menu_gp_id":item["permissions__menu_gp_id"],
50             "menu_id":item["permissions__group__menu_id"],
51             "menu_title":item["permissions__group__menu__caption"]
52         }
53         menu_list.append(tpl)
54     request.session[settings.PERMISSION_MENU_KEY] = menu_list
55     print("============",menu_list)
sever下的init_permission.py

5、app01下的views

views.py
 1 from django.shortcuts import render, redirect, HttpResponse
 2 from django.conf import settings
 3 # Create your views here.
 4 from rbac import models
 5 import re
 6 from rbac.service.init_permission import init_permission
 7 class BasePagPermission(object):
 8     def __init__(self, code_list):
 9         self.code_list = code_list
10 
11     def has_add(self):
12         if "add" in self.code_list:
13             return True
14 
15     def has_del(self):
16         if "del" in self.code_list:
17             return True
18 
19     def has_edit(self):
20         if "edit" in self.code_list:
21             return True
22 
23 
24 def login(request):
25     if request.method == "GET":
26         return render(request, "login.html")
27     else:
28         username = request.POST.get("username")
29         password = request.POST.get("password")
30         user = models.UserInfo.objects.filter(name=username, password=password).first()
31         if user:
32             init_permission(user, request)
33             return redirect("/userinfo/")
34         else:
35             return render(request, "login.html")
36 
37 
38 def index(request):
39     return render(request, "index.html")
40 
41 
42 def userinfo(request):
43     pagpermission = BasePagPermission(request.permission_code_url)  # 實例化
44     # print("code......", request.permission_code_url)
45     data_list = [
46         {"id": 1, "name": "haiyan1"},
47         {"id": 2, "name": "haiyan2"},
48         {"id": 3, "name": "haiyan3"},
49         {"id": 4, "name": "haiyan4"},
50         {"id": 5, "name": "haiyan5"},
51     ]
52     #print("data_list",data_list)
53     #print("pagpermission",pagpermission)
54     return render(request, "userinfo.html", {"data_list": data_list, "pagpermission": pagpermission})
55 
56 
57 def userinfo_add(request):
58     if request.method == "GET":
59         return render(request,"userinfo_add.html")
60     else:
61         return redirect("/userinfo/")
62 
63 
64 def userinfo_del(request, nid):
65     return HttpResponse("刪除用戶")
66 
67 
68 def userinfo_edit(request, nid):
69     return HttpResponse("編輯用戶")
70 
71 
72 def order(request):
73     pagpermission = BasePagPermission(request.permission_code_url)  # 實例化
74     print("code......", request.permission_code_url)
75     return render(request,"order.html",{"pagpermission":pagpermission})
76 
77 
78 def order_add(request):
79     return HttpResponse("添加訂單")
80 
81 
82 def order_del(request, nid):
83     return HttpResponse("刪除訂單")
84 
85 
86 def order_edit(request, nid):
87     return HttpResponse("編輯訂單")
views.py

 

6、中間件

 1 #!usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from django.shortcuts import render, redirect, HttpResponse
 4 from django.conf import settings
 5 import re
 6 
 7 
 8 class MiddlewareMixin(object):
 9     def __init__(self, get_response=None):
10         self.get_response = get_response
11         super(MiddlewareMixin, self).__init__()
12 
13     def __call__(self, request):
14         response = None
15         if hasattr(self, 'process_request'):
16             response = self.process_request(request)
17         if not response:
18             response = self.get_response(request)
19         if hasattr(self, 'process_response'):
20             response = self.process_response(request, response)
21         return response
22 
23 
24 class Middle(MiddlewareMixin):  # 必須去繼承這個類
25     def process_request(self, request):
26         current_url = request.path_info  # 獲取當前請求的路徑
27 
28         # 如果匹配的是白名單里面的就讓通過,不需要權限
29         for url in settings.WHITE_LIST:
30             if re.match(url, current_url):
31                 return None
32         permission_dict = request.session.get(settings.PERMISSION_URL_DICT)  # 獲取session
33         if not permission_dict:  # 如果沒有得到,就直接跳轉到login頁面
34             return redirect("/login/")
35 
36         flag = False
37         for group_id, code_url in permission_dict.items():
38             for db_url in code_url["urls"]:
39                 regex = "^{0}$".format(db_url)
40                 # 因為match匹配的時候會把你只要有的都匹配到了,我們只匹配當前的url,所以得加一個起始終止符
41                 # print(regex, current_url)
42                 if re.match(regex, current_url):
43                     # print(1111111)
44                     request.permission_code_url = code_url["code"]  # 用戶輸入的url和數據庫的url匹配成功之后成功之后先把code保存在request中,方便以后判斷
45                     flag = True
46                     break  # 如果匹配成功就進入頁面
47                     # 注意在這里不能用return,在中間件中process_request這個函數如果有return就只會執行自己的
48                     #   response和上面的response,不會執行后續的。沒有return就會去繼續執行后續中間件和視圖函數
49             if flag:  # 結束外層循環
50                 break
51         if not flag:
52             return HttpResponse("無權訪問")  # 如果訪問不成功就顯示無權訪問
53 
54     def process_reponse(self, request, response):
55         return response
middlewear下的rbac.py

7、templatetags下的rbac.py

 1 #!usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from django.conf import settings
 4 import re
 5 from django.template import Library
 6 register = Library()
 7 @register.inclusion_tag("xxxx.html")
 8 def menu_html(request):
 9     """
10        去Session中獲取菜單相關信息,匹配當前URL,生成菜單
11        :param request:
12        :return:
13        """
14     menu_list = request.session.get(settings.PERMISSION_MENU_KEY)
15     current_url = request.path_info
16     menu_dict = {}
17     for item in menu_list:
18         # 循環找到可以作為菜單的權限
19         if not item["menu_gp_id"]:
20             menu_dict[item["id"]] = item
21     # 正則匹配添加active
22     for item in menu_list:
23         regex = "^{0}$".format(item["url"])
24         if re.match(regex, current_url):
25             # 匹配成功在根據id去判斷,如果菜單id有值就不是菜單,則去找它的值對應的id,添加active
26             # ,為null時就是菜單,直接給自己添加一個active
27             if not item["menu_gp_id"]:  #是菜單
28                 menu_dict[item["id"]]["active"] = True
29             else:
30                 menu_dict[item["menu_gp_id"]]["active"] = True
31 
32     result = {}
33     for item in menu_dict.values():
34         active = item.get("active")
35         menu_id = item["menu_id"]
36         if menu_id in result:
37             result[menu_id]["children"].append({'title': item['title'], 'url': item['url'], 'active': active})
38             if active:
39                 result[menu_id]["active"] = True
40         else:
41             result[menu_id] = {
42                 'menu_id': item['menu_id'],
43                 'menu_title': item['menu_title'],
44                 'active': active,
45                 'children': [
46                     {'title': item['title'], 'url': item['url'], 'active': active}
47                 ]
48             }
49     print("result",result)
50     return {"menu_dict":result}
自定義標簽rbac.py

 

8、template

 1 {% load rbac %}
 2 <!DOCTYPE html>
 3 <html lang="en">
 4 <head>
 5     <meta charset="UTF-8">
 6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 7     <meta name="viewport" content="width=device-width">
 8     <title>Title</title>
 9     <link rel="stylesheet" href="/static/rbac/rbac.css">
10 </head>
11 <body>
12 <div class="aaa">
13     <div class="left">
14         {% menu_html request %}
15     </div>
16     <div class="right">
17         {% block content %}
18 
19         {% endblock %}
20     </div>
21 </div>
22 <script src="/static/jquery-3.2.1.min.js"></script>
23 <script src="/static/rbac/rbac.js"></script>
24 
25 </body>
26 </html>
base.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width">
 7     <title>Title</title>
 8 </head>
 9 <body>
10 <h1>hello--{{ user.name }}</h1>
11 </body>
12 </html>
index.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width">
 7     <title>Title</title>
 8 </head>
 9 <body>
10 <form method="post" action="/login/">
11     {% csrf_token %}
12     <p>姓名:<input type="text" name="username"></p>
13     <p>密碼:<input type="password" name="password"></p>
14     <p><input type="submit" value="提交"></p>
15 </form>
16 </body>
17 </html>
login.html
1 {% extends "base.html" %}
2 {% block content %}
3 <h1>訂單頁面</h1>
4 {% endblock %}
order.html
 1 {% extends "base.html" %}
 2 {% block content %}
 3 {% if pagpermission.has_add %}
 4         <a href="/userinfo/add/">添加</a>
 5         {% endif %}
 6         <table border="1">
 7             <thead>
 8                 <th>編號</th>
 9                 <th>姓名</th>
10                 <th>操作</th>
11             </thead>
12             <tbody>
13             {% for row in data_list %}
14                 <tr>
15                     <td>{{ row.id }}</td>
16                     <td>{{ row.name }}</td>
17                     <td>
18                         {% if pagpermission.has_edit %}
19                          <a href="#">編輯</a>
20                         {% endif %}
21                        {% if pagpermission.has_del %}
22                         <a href="#">刪除</a>
23                        {% endif %}
24                     </td>
25                 </tr>
26             {% endfor %}
27             </tbody>
28         </table>
29 {% endblock %}
userinfo.html
1 {% extends "base.html" %}
2 {% block content %}
3 <form action="" method="post">
4     {% csrf_token %}
5     <p>編號:<input type="text" name="bianhao"></p>
6     <p>姓名:<input type="text" name="name"></p>
7     <input type="submit" value="提交">
8 </form>
9 {% endblock %}
userinfo_add.html
 1 {% for k,item in menu_dict.items %}
 2  <div class="item-title">{{ item.menu_title }}</div>
 3      {% if item.active %}
 4             <div class="item-permission">
 5         {% else %}
 6             <div class="item-permission hide">
 7         {% endif %}
 8         {% for v in item.children %}
 9             {% if v.active %}
10                     <a href="{{ v.url }}" class="active">{{ v.title }}</a>
11             {% else %}
12                     <a href="{{ v.url }}">{{ v.title }}</a>
13             {% endif %}
14         {% endfor %}
15     </div>
16 {% endfor %}
17 
18 {# <div class="item-title">菜單一</div>#}
19 {#        <div class="item-permission">#}
20 {#            <a href="">用戶列表</a>#}
21 {#            <a href="">訂單列表</a>#}
22 {#        </div>#}
23 {#    <div class="item-title">菜單二</div>#}
24 {#        <div class="item-permission hide">#}
25 {#            <a href="">用戶列表</a>#}
26 {#            <a href="">訂單列表</a>#}
27 {#        </div>#}
xxxx.html

9、static---rbac---rbac.css

 1 .left{
 2     float: left;
 3     width: 20%;
 4     height: 500px;
 5     background-color: coral;
 6     padding: 20px 20px;
 7 }
 8 .right{
 9     width: 80%;
10     height: 500px;
11     background-color: azure;
12 }
13 .item-permission a{
14     display: block;
15 }
16 .hide{
17     display: none;
18 }
19 .item-permission a.active{
20     color: red;
21 }
rbac.css

10、static---rbac---rbac.js

 1  // 方式一
 2 $(function () {
 3         $(".item-title").click(function () {
 4               $(this).next().toggleClass("hide")
 5         })
 6     });
 7 // 方式二:
 8 //  $(function () {
 9 //     $('.item-title').click(function () {
10 //         if($(this).next().hasClass('hide')){
11 //             $(this).next().removeClass('hide')
12 //         }else{
13 //             $(this).next().addClass('hide')
14 //         }
15 //     })
16 //  });
rbac.js

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM