Django如何建立一套介面級別的許可權系統
從零開始搭建當然是可以的,但是Django的特色就是大而全,所以,我的方案是,利用現有的Django框架,實現功能。 我用的pycharm,操作很方便快捷。
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_content_type |
先看看你的資料庫,這些表,就是咱們建立許可權系統會使用的所有資料表了,都是自動生成的,少哪個,自己百度去
from django.contrib.auth.models import Permission
ctrl+滑鼠左鍵,點選Permission,然後在開啟的原始碼頁面,上邊的頁面標籤(auth/models.py)那裡,右鍵,copy path,使用pycharm,點file,open,貼上,刪除貼上字串裡面最後的“/models.py”,
... .../site-packages/django/contrib/auth
OK,open in new windows,OK,進去之後,像進入一個專案一樣,這樣非常有利於你瞭解原始碼。 如何快速瞭解一個Django專案?進去先看models。 如何一目瞭然的檢視一個.py檔案的結構?點pycharm的view,tool windows,structure,把一級標題都摺疊起來!
update_last_login
PermissionManager
Permission
GroupManager
Group
UserManager
_user_get_all_permissions
_user_has_perm
_user_has_module_perms
PermissionsMixin
AbstractUser
User
AnonymousUser
百度翻譯一下,瞭解這些類都是什麼。不要全扔百度翻譯,要先分詞:
- PermissionManager許可經理
- Permission n.允許;批准,正式認可,認可
- manager n.處理者,經理,管理人;幹事,理事; 〈美〉(政黨等的)領袖;策士,幹才,幹練的人
顯然差別很大。 manager結尾的(PermissionManager),是模型管理器類,和他前面一樣的(Permission),是模型類。其他也是。
Permission
Group
User
這三個類,就是咱們需要仔細瞭解的,乾貨! 看看他的欄位,還有他的父類的欄位。 Permission:
content_type = models.ForeignKey(
ContentType,
models.CASCADE,
verbose_name=_('content type'),
)
所以,你想建立許可權,需要有對應的ContentType。 再去看看ContentType類,方法同上,ctrl+左鍵追蹤原始碼,複製路徑,pycharm開啟,瞭解一下。
class ContentType(models.Model):
app_label = models.CharField(max_length=100)
model = models.CharField(_('python model class name'), max_length=100)
就是字面意思,app名字和model名字。但是他的資料是根據你遷移時候,自動生成的,不是關聯的。這意味著,咱們也可以,手動新增。 隨便找個你專案裡面的app,在admin.py裡面加上
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
@admin.register(Permission)
class CompanyAdmin(admin.ModelAdmin):
list_display = ('id','name','content_type','codename')
@admin.register(ContentType)
class CompanyAdmin(admin.ModelAdmin):
list_display = ('id','app_label','model')
然後,開啟django自帶的後臺,/admin,就可以看到這兩個模型類: 如果groups和users沒有,自己百度去,差不多的,應該。
- 然後建立一個自定義的ContentType,儲存;
- 建立一個新的Permission,其中外來鍵取剛剛建立的ContentType,其他先隨便寫上點什麼顯眼的字元。
- 這樣就有許可權了,可以給groups和users分配剛剛建立的新許可權。 現在咱們實現了許可權的創立,下一步需要把他繫結到每一個介面上面,使客戶端訪問每一個介面時,都會檢查一下許可權。 如果你django使用的檢視類,就ctrl+左鍵追蹤檢視類的父類,
from rest_framework.views import APIView
APIView裡面的
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
這個的意思是,initial初始化的時候,會走這幾步。咱們建立一個APIView的子類,把check_permissions重寫一下,然後,需要檢查介面許可權的檢視類,直接繼承這個新寫的CheckPermissionView,就可以完成,每個介面都檢測是否擁有許可權的需求。
class CheckPermissionView(AllowAnyView):
def check_permissions(self, request):
# print(request.path_info)
# print(self.__class__.__name__)
codename = request.path_info.split("/")[1] + "/" + self.__class__.__name__
# print(codename) # app_name/view_class_name
if codename[0] == "/":
codename = "swagger"
user_id = request.user.id
# print('user_id '*30)
# print(user_id)
if not user_id:
raise BusinessException("請登入之後再訪問此介面")
group = Group.objects.filter(permissions__codename=codename,user__id=user_id).first()
if not group:
raise BusinessException("你的許可權不足以訪問此介面,若有需要,請聯絡管理員開通許可權")
BusinessException是一個自定義錯誤,繼承自Exception,這裡不多說,不會寫的,百度一下。 至於許可權名字是如何定義的,你把我的註釋開啟,打印出來,就知道了。 一個介面對應一個許可權,可以把一堆介面許可權,都分給一個新建立的groups,然後,需要這些許可權的users,直接加入groups,就可以輕鬆實現,介面粒度的許可權管理。 全程程式碼不多,但是需要對原始碼有一定程度的理解,其他就是填許可權麻煩一點點(當然可以使用SQL直接插入資料庫,我感覺這樣快一點點。SQL直接程式碼操作,生成還是很快的。不用挨個填admin後臺)。 如果我的文章,對你有一點點幫助的話,請幫忙在右邊小心心那裡點贊一下,碼字不易,也是為了將來找工作好找一點,O(∩_∩)O謝謝!