Django內置權限擴展案例

當Django的內置權限無法滿足需求的時候就自己擴展吧~

背景介紹

overmind項目使用了Django內置的權限系統,Django內置權限系統基于model層做控制,新的model創建后會默認新建三個權限,分別為:add、change、delete,如果給用戶或組賦予delete的權限,那么用戶將可以刪除這個model下的所有數據。

原本overmind只管理了我們自己部門的數據庫,權限設置只針對具體的功能不針對細粒度的數據庫實例,例如用戶A 有審核的權限,那么用戶A 可以審核所有的DB,此時使用內置的權限系統就可以滿足需求了,但隨著系統的不斷完善要接入其他部門的數據庫管理,這就要求針對不同用戶開放不同DB的權限了,例如A部門的用戶只能操作A部門的DB,Django內置基于model的權限無法滿足需求了。

實現過程

先來確定下需求:

  1. 保持原本的基于功能的權限控制不變,例如用戶A有查詢權限,B有審核權限
  2. 增加針對DB實例的權限控制,例如用戶A只能查詢特定的DB,B只能審核特定的DB

對于上邊需求1用內置的權限系統已經可以實現,這里不贅述,重點看下需求2,DB信息都存放在同一個表里,不同用戶能操作不同的DB,也就是需要把每一條DB信息與有權限操作的用戶進行關聯,為了方便操作,我們考慮把DB跟用戶組關聯,在用戶組里的用戶都有權限,而操作類型經過分析主要有兩類讀和寫,那么需要給每個MySQL實例添加兩個字段分別記錄對此實例有讀和寫權限的用戶組

如下代碼在原來的model基礎上添加read_groupswrite_groups字段,DB實例跟用戶組應是ManyToManyField多對多關系,一個實例可以關聯多個用戶組,一個用戶組也可以屬于多個實例

class Mysql(models.Model):Env = ((1, 'Dev'),(2, 'Qa'),(3, 'Prod'),)create_time = models.DateTimeField(auto_now_add=True, verbose_name='創建時間')update_time = models.DateTimeField(auto_now=True, verbose_name='更新時間')project_id = models.IntegerField(verbose_name='項目')project_tmp = models.CharField(max_length=128, default='')environment = models.IntegerField(choices=Env, verbose_name='環境')master_host = models.GenericIPAddressField(verbose_name='master主機')master_port = models.IntegerField(default=3306, verbose_name='master端口')slave_host = models.GenericIPAddressField(null=True, verbose_name='slave主機')slave_port = models.IntegerField(null=True, default=3306, verbose_name='slave端口')database = models.CharField(max_length=64, verbose_name='數據庫')read_groups = models.ManyToManyField(Group, related_name='read', verbose_name='讀權限')write_groups = models.ManyToManyField(Group, related_name='write', verbose_name='寫權限')description = models.TextField(null=True, verbose_name='備注')

model確定了,接下來我們分三部分詳細介紹下權限驗證的具體實現

列表頁權限控制

8fqkJd2s8HJjQAAAAASUVORK5CYII=

如上圖列表頁,每個用戶進入系統后只能查看自己有讀權限的MySQL實例列表,管理員能查看所有,代碼如下:

def mysql(request):if request.method == 'GET':if request.user.is_superuser:_lists = Mysql.objects.all().order_by('id')else:# 獲取登錄用戶的所有組_user_groups = request.user.groups.all()# 構造一個空的QuerySet然后合并_lists = Mysql.objects.none()for group in _user_groups:_lists = _lists | group.read.all()return render(request, 'overmind/mysql.index.html', {'request': request, 'lPage': _lists})

實現的思路是:獲取登錄用戶的所有組,然后循環查詢每個組有讀取權限的數據庫實例,最后把每個組有權限讀的數據庫實例進行合并返回

獲取登錄用戶的所有組用到了ManyToMany的查詢方法:request.user.groups.all()

最終返回的一個結果是QuerySet,所以我們需要先構造一個空的Queryset:Mysql.objects.none()

QuerySet合并不能用簡單的相加,應為:QuerySet-1 | QuerySet-2

查詢接口權限控制

A9upb9Dm1JoCAAAAAElFTkSuQmCC

如上圖系統中有很多功能是需要根據項目、環境查詢對應的DB信息的,對于此類接口也需要控制用戶只能查詢自己有權限讀的DB實例,管理員能查看所有,代碼如下:

def get_project_database(request, project, environment):if request.method == 'GET':_jsondata = {}if request.user.is_superuser:# 返回所有項目和環境匹配的DB_lists = Mysql.objects.filter(project_id=int(project),environment=int(environment))_jsondata = {i.id: i.database for i in _lists}else:# 只返回用戶有權限查詢的DB_user_groups = request.user.groups.all()for group in _user_groups:# 循環mysql表中有read_groups權限的所有組for mysql in group.read.all():if mysql.project_id == int(project) and mysql.environment == int(environment):_jsondata[mysql.id] = mysql.databasereturn JsonResponse(_jsondata)

實現思路與上邊類似,只是多了一步根據項目和環境再進行判斷

需要根據group去反查都有哪些DB實例包含了該組,這里用到了M2M的related_name屬性:group.read.all()

更多關于Django ORM查詢的內容可以看這篇文章Django model select的各種用法詳解有詳細的總結

執行操作權限控制

除了上邊的兩個場景之外我們還需要在執行具體的操作之前去判斷是否有權限,例如執行審核操作前判斷用戶是否對此DB有寫權限

有很多地方都需要做這個判斷,所以把這個權限判斷單獨寫個方法來處理,代碼如下:

def check_permission(perm, mysql, user):# 如果用戶是超級管理員則有權限if user.is_superuser:return True# 取出用戶所屬的所有組_user_groups = user.groups.all()# 取出Mysql對應權限的所有組if perm == 'read':_mysql_groups = mysql.read_groups.all()if perm == 'write':_mysql_groups = mysql.write_groups.all()# 用戶組和DB權限組取交集,有則表示有權限,否則沒有權限group_list = list(set(_user_groups).intersection(set(_mysql_groups)))return False if len(group_list) == 0 else True

實現思路是:根據傳入的第三個用戶參數,來獲取到用戶所有的組,然后根據傳入的第一個參數類型讀取或寫入和第二個參數DB實例來獲取到有權限的所有組,然后對兩個組取交集,交集不為空則表示有權限,為空則沒有

M2M的.all()取出來的結果是個list,兩個list取交集的方法為:list(set(list-A).intersection(set(list-B)))

view中使用就很簡單了,如下:

def query(request):if request.method == 'POST':postdata = request.body.decode('utf-8')_host = get_object_or_404(Mysql, id=int(postdata.get('database')))# 檢查用戶是否有DB的查詢權限if check_permission('read', _host, request.user) == False:return JsonResponse({'state': 0, 'message': '當前用戶沒有查詢此DB的權限'})

寫在最后

  1. Django有第三方的基于object的權限管理模塊Django-guardian,本項目沒有使用主要是因為一來權限需求并不復雜,自己實現也很方便,二來個人在非必要的情況下并不喜歡引用過多第三方的包,后續升級維護都是負擔
  2. 方案和代碼不盡完美,各位有更好的方案建議或更優雅的代碼寫法歡迎與我交流

o_scan.qrcode.png

相關文章推薦閱讀:

  • Django+JWT實現Token認證
  • 我們自研的那些Devops工具

轉載于:https://www.cnblogs.com/37Y37/p/10514575.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449674.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449674.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449674.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java 從入門到高級學習路線

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 Java 從入門到高級學習路線《一》1.Jvm 部分Jvm 內存模型、Jvm 內存結構、Jvm 參數調優、Java 垃圾回收《二》Java 基礎部分1.必須會使用…

Flutter Mac iOS 環境配置

官方文檔:flutter.io/docs/get-st… 1.需要的命令行工具 bash curl git 2.x mkdir rm unzip which 2.SDK下載地址 flutter_macos_v1.0.0-stable.zip storage.googleapis.com/flutter_inf… 3.解壓Flutter SDK cd ~/Flutter/SDK $ unzip ~/Downloads/flutter_macos_v…

多線程研究1

單線程: from urllib.request import urlretrieve import time import random starttime.time() fopen(E:\Python\py\web\hh.txt,r)#打開存放URL的文件 af.readlines() f.close() for i in a:brandom.randint(0,30)urlretrieve(i,%d.png%b) endtime.time() print(…

android viewpage預加載和懶加載問題

1、本人理解懶加載和預加載問題某種情況下可以歸結為一類問題,下面我就說一下我遇到的預加載問題和懶加載問題及解決的相應方法: - [1 ] 預加載問題 描述:我用到了三個fragment、viewpage及tablayout實現點擊切換、滑動切換。 …

大數據,且行且思

“大數據”概念于20世紀90年代被提出,最初只是對一些在一定時間內無法用傳統方法進行抓取、管理和處理的數據的統稱。隨著時間的推移和科技的發展以及物聯網、移動互聯網、SNS的興起,每年產生的數據量都以幾何級數增長,《IDC Digital Univers…

IntelliJ IDEA中新建JAVA WEB項目、maven項目

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 在IntelliJ IDEA 中新建一個Web應用項目。 1、 在主界面頂部菜單欄依次“File”-"New"-"Project..." 2、在對話框中…

S/4HANA業務角色概覽之訂單到收款篇

2019獨角獸企業重金招聘Python工程師標準>>> 大家好我叫Sean Zhang,中文名張正永。目前在S/4HANA產品研發部門任職產品經理,而這一階段要從2017年算起,而在那之前接觸更多還是技術類的,比如做過iOS、HANA、ABAP、UI5等…

掘金量化的一個代碼,對本人寫策略避免入坑有重要意義

# codingutf-8from __future__ import print_function, absolute_import, unicode_literalsfrom gm.api import *import numpy as npdef init(context):# 選擇的兩個合約context.symbol [DCE.j1901, DCE.jm1901]# 訂閱歷史數據subscribe(symbolscontext.symbol,frequency1d,co…

C++ STL學習筆記

C STL學習筆記一 為何要學習STL: 數據結構與算法是編程的核心,STL中包含各種數據結構和優秀的算法,確實值得深入學習,本文中雖然著重使用,但希望有心的朋友能多看看相關數據結構的實現,對于C語言確實會有較…

ItelliJ IDEA開發工具使用—創建一個web項目

轉自:https://blog.csdn.net/wangyang1354/article/details/50452806概念需要明確一下IDEA中的項目(project)與eclipse中的項目(project)是不同的概念,IDEA的project 相當于之前eclipse的workspace,IDEA的M…

AKOJ-2037-出行方案

鏈接:https://oj.ahstu.cc/JudgeOnline/problem.php?id2037 題意: 安科的夏天真是不一般的熱,避免炎熱,伍學長因此想為自己規劃一個校園出行方案,使得從宿舍出發到校園的各個地方距離花費時間最短。我們已知校園一共有…

akshare 布林通道策略

import datetime import pandas as pd import backtrader as bt import matplotlib.pyplot as plt from datetime import datetime import matplotlib import akshare as ak %matplotlib inline class Boll_strategy(bt.Strategy):#自定義參數,每次買入1800手param…

一些資源網站..

github上各種免費編程書籍~~~ : https://github.com/EbookFoundation/free-programming-books/blob/master/free-programming-books-zh.md正則表達式學習 :https://web.archive.org/web/20161119141236/http://deerchao.net:80/tutorials/regex/regex.htmtorch:http…

極客無極限 一行HTML5代碼引發的創意大爆炸

摘要:一行HTML5代碼能做什么?國外開發者Jose Jesus Perez Aguinaga寫了一行HTML5代碼的文本編輯器。這件事在分享到Code Wall、Hacker News之后,引起了眾多開發者的注意,紛紛發表了自己的創意。 這是最初的HTML5代碼,它…

c# 寫文件注意問題及用例展示

以txt寫string舉例,正確代碼如下: private void xie(){FileStream fs new FileStream("1.txt", FileMode.Create);StreamWriter sw new StreamWriter(fs, Encoding.Default);sw.Write("123");sw.Flush();sw.Close();//fs.Flush();…

akshare sma策略

import datetimeimport pandas as pdimport backtrader as bt from datetime import datetime import matplotlib import akshare as ak %matplotlib inlineclass SmaCross(bt.Strategy):# 全局設定交易策略的參數params ((pfast, 5), (pslow, 20),)def __init__(self):sma1 …

DOCKER windows 7 詳細安裝教程

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 DOCKER windows安裝 DOCKER windows安裝 1.下載程序包2. 設置環境變量3. 啟動DOCKERT4. 分析start.sh5. 利用SSH工具管理6. 下載鏡像 6.1…

c#UDP協議

UDP協議是不可靠的協議,傳輸速率快 服務器端: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;using System.Net.Sockets; using System.Net; using System.Threading;namespace…

芝麻信用免押金成趨勢 報告稱租賃經濟有望突破10萬億元

中新網1月16日電 “很多物品都是租來的,但生活不是。”如今,越來越多的年輕人選擇了“租”生活,從房子到車子,從服飾到電腦,甚至玩具、嬰兒車,全都可以租用,租賃已成為當下年輕人追求品質生活的…

開發者成功學:扔掉你那些很sexy的想法

摘要:在開發者的世界里,開發iPhone應用并不像表面那么光鮮,收支不成正比是常有之事,勞心勞力開發的應用無人問津更是屢見不鮮。走出了開發的一小步卻難以邁出銷售推廣上的一大步,究竟如何才能將應用賣出去并獲取利潤&a…