1. 程式人生 > >Django如何建立一套介面級別的許可權系統

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,把一級標題都摺疊起來!

現在,c 圖示開頭的,都是類,f 圖示開頭的都是函式。

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沒有,自己百度去,差不多的,應該。

  1. 然後建立一個自定義的ContentType,儲存;
  2. 建立一個新的Permission,其中外來鍵取剛剛建立的ContentType,其他先隨便寫上點什麼顯眼的字元。
  3. 這樣就有許可權了,可以給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謝謝!