一.8.django權限管理/drf權限管理


1.什么是權限管理:
.權限管理,一般指根據系統設置的安全規則或者安全策略,用戶可以訪問而且只能訪問自己被授權的資源
.權限管理好比如鑰匙,有了鑰匙就能把門打開,但是權限設置是有級別之分的,假如這個系統有多個權限級別就如一間屋有多個門,想要把所有門都打開您必須要取得所有的鑰匙,就如系統一樣。

2.django權限機制:
  django權限機制能夠約束用戶行為,控制頁面的顯示內容,也能使API更加安全和靈活;用好權限機制,能讓系統更加強大和健壯

3.django權限控制:
  Django用user, group和permission完成了權限機制,這個權限機制是將屬於model的某個permission賦予user或group,可以理解為全局的權限,即如果用戶A對數據模型(model)B有可寫權限,那么A能修改model B的所有實例(objects)。group的權限也是如此,如果為group C 賦予model B的可寫權限,則隸屬於group C 的所有用戶,都可以修改model B的所有實例。

4.Django的權限項:
  Django用permission對象存儲權限項,每個model默認都有三個permission,即add model, change model和delete model
  permission總是與model對應的,如果一個object不是model的實例,我們無法為它創建/分配權限

5.默認權限:
  在 INSTALLED_APPS 設置中列出 django.contrib.auth 后,安裝的各個應用中的每個 Django 模型默認都有三個權限:添加、修改和刪除。每次運行 manage.py migrate 命令  創建新模型時都會為其賦予這三個權限。

6.分組:

  django.contrib.auth.models.Group 模型是為用戶分類的通用方式,這樣便可以為一批用戶賦予權限或添加其 他標注。用戶所屬的分組數量不限。一個分組中的用戶自動獲得賦予那個分組的權限。

  除了權限之外,分組還是為用戶分類的便捷方式,分組后可以給用戶添加標簽,或者擴展功能

7.權限應用:

Permission

User Permission

Group Permission

8.權限檢查

Permission:

  .Django定義每個model后,默認都會添加該model的add, change和delete三個permission,自定義的permission可以在我們定義model時手動添加

class Server(models.Model):

    ...    

    class Meta:        

        permissions = (            

            ("view_server", "can view server"),            

            ("change_server_status", "Can change the status of server"),        

        )

  .每個permission都是django.contrib.auth.Permission類型的實例,該類型包含三個字段name, codename 和 content_type,

content_type反應了permission屬於哪個model,

codename 如上面的view_server,代碼邏輯中檢查權限時要用, 

name是permission的描述,將permission打印到屏幕或頁面時默認顯示的就是name

9.User Permission:

User對象的user_permission字段管理用戶的權限:

  user = User.objects.get(username="rock")

  user.user_permissions = [permission_list]

  user.user_permissions.add(permission, permission, …) #增加權限 

  user.user_permissions.remove(permission, permission, …) #刪除權限 

  user.user_permissions.clear() #清空權限

  user.get_all_permissions() #列出用戶的所有權限

  user.get_group_permissions() # 列出用戶所屬group的權限

10.Group Permission:

  group permission管理邏輯與user permission管理一致,group中使用permissions字段做權限管理: 

    group.permissions.set([permission_list])

    group.permissions.add(permission, permission, …) 

    group.permissions.remove(permission, permission, …) 

    group.permissions.clear()

11.權限驗證-普通視圖:

  在視圖中驗證權限—— permission_required

當業務邏輯中涉及到權限檢查時,decorator能夠分離權限驗證和核心的業務邏輯,使代碼更簡潔,邏輯更清晰。permission的decorator為permission_required

from django.contrib.auth.decorators import login_required, permission_required 

@login_required   --表示你必須要登錄

@permission_required(’dashboard.view_server')  ---表示你必須有權限才可以

def my_view(request):

    ...

12.權限驗證-類視圖:

from django.utils.decorators import method_decorator

from django.contrib.auth.decorators import login_required, permission_required

class ServerView(TemplateView):

    @method_decorator(login_required)

    @method_decorator(permission_required(“dashboard.view_server”)

    def get(self, request, *args, **kwargs):

        ...

13.權限驗證-view代碼中驗證:

if not request.user.has_perm(’dashboard.view_server')

    return HttpResponse('Forbidden')

14.權限驗證-模板中驗證:

  驗證是否有登陸 {% if user.is_authenticated %} <p>Welcome, {{ user.username }}. Thanks for logging in.</p> {% else %} <p>Welcome, new user. Please log in.</p> {% endif %}

  驗證是否有權限 {% if perms.dashboard.view_server %} 有權限 {% endif %}

15.自定義PermissionRequiredMixin: 創建僅限 .在模型的 Meta 類中定制權限 class Meta: permissions = ( ("modify_user_status", "修改用戶狀態"), ("modify_user_passwd", "修改用戶密碼"), ) 

 一.drf權限管理

1.簡單權限應用---只有登錄過的用戶才能訪問

(1).apps/users/views.py:

from django.shortcuts import render
from rest_framework import viewsets
from django.contrib.auth import get_user_model
from .serializers import UserSerializer
from .filters import UserFilter
from rest_framework.permissions import IsAuthenticated

User = get_user_model()
class UserViewset(viewsets.ReadOnlyModelViewSet):
    '''
    這個用戶資源的viewset會給外面暴露兩個接口retrieve和list
    retrieve:返回指定用戶信息對象--單個對象的字段是在用戶序列化類serializers.py中定義
     list:返回用戶列表--列表的字段的字段是在用戶序列化類serializers.py中定義
    '''
    #1.指定queryset
    queryset = User.objects.all()
    #2.指定序列化類
    serializer_class = UserSerializer
    #(2)按哪個字段搜索:
    filter_fields = ('username',"email")
    #(3)使用哪個filter類
    filter_class = UserFilter
    #權限為必須得登錄才能認證:
    permission_classes = (IsAuthenticated,)

效果如下圖:

那怎么認證?--得用drf的認證

  drf提供了一套基於原始的認證即session認證,它的認證是只需配一登錄頁面即可。

(2)devops/urls.py中添加一路由:

urlpatterns = [
    url(r'^', include(route.urls)),
    url(r'^aip-auth', include("rest_framework.urls",namespace="reset_framework")),
    url(r'^docs/', include_docs_urls("lizhihua運維平台接口文檔"))
]

 

(python36env) [vagrant@CentOS7 devops]$ python manage.py createsuperuser
Username (leave blank to use 'vagrant'): admin
Email address: admin@51reboot.com
Password: 123456 

 這樣就可訪問了!

2.全局權限應用--模型權限(必須跟模型關聯):

  查看權限源碼文件如下圖中可知它已對內置很很多權限,那這樣我就可自定義權限繼承其中任何一權限類即可:

 

 但是閱讀源碼發現它的模型權限中沒有添加get認證/權限驗證,只有如下方法有權限驗證:

class DjangoModelPermissions(BasePermission):
    perms_map = {
        'GET': [],    ----空/沒有
        'OPTIONS': [],
        'HEAD': [],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }
........

(1)settins.py:配置全局模型權限

查看參考源碼配置如下圖:但是allowany所有人均可訪問不是我要的,所以我覆蓋它默認配置--改為django的模型權限,這樣就全局生效,好處是不用在每個app的視圖中都寫,但不好的是如果你一但寫一個filter,沒有queryset就會出錯--解決:就是在app中自定不使用全局的,使用自己獨立的即可,這里先使用全局的即可,只做如下配置,app的views.py中不作任何配置。

REST_FRAMEWORK = {
 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
    'PAGE_SIZE':10,
    'DEFAULT_PAGINATION_CLASS':'users.pagination.Pagination',
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.DjangoModelPermissions', ],
}
創建普通用戶
(python36env) [vagrant@CentOS7 devops]$ python manage.py shell
n [1]: from django.contrib.auth.models import User                  

In [2]: User.objects.create_user("rock","rock@51reboot.com","123456")

登錄后效果如下:--所有的測試頁面都只有看的權限

 3.drf自定義get權限

  因為django默認支持的模型權限中沒有get的,所以我可直接自定並覆蓋它默認的,

 (1)devops/permissions.py中:

from rest_framework.permissions import DjangoModelPermissions

class Permissions(DjangoModelPermissions):
    #
    def get_custom_perms(self, view, method):
        if hasattr(view, "extra_perm_map"):
            if isinstance(view.extra_perm_map, dict):
                return view.extra_perm_map.get(method,[])
        return []

    #這個方法必須寫,我是直接把django模型權限中的必備的has_permission方法拷過來
    def has_permission(self, request, view):
        if getattr(view, '_ignore_model_permissions', False):
            return True
        if not request.user or (
           not request.user.is_authenticated and self.authenticated_users_only):
            return False
        queryset = self._queryset(view)
        perms = self.get_required_permissions(request.method, queryset.model)
        perms.extend(self.get_custom_perms(view, request.method))
        return request.user.has_perms(perms)

(2)全局配置替換掉:

REST_FRAMEWORK = {
 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
    'PAGE_SIZE':10,
    'DEFAULT_PAGINATION_CLASS':'users.pagination.Pagination',
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
 'DEFAULT_PERMISSION_CLASSES': [
        # 'rest_framework.permissions.DjangoModelPermissions',
        'devops.permissions.Permissions',
    ]
}

 4.不使用queryset即模型的權限---viewset權限

class DashboardStatusViewset(viewsets.ViewSet):
    """
    list:
    獲取dashboard狀態數據
    """
    permission_classes = (permissions.IsAuthenticated,)
    def list(self, request, *args, **kwargs):
        data = self.get_content_data()
        return response.Response(data)

    def get_content_data(self):
        return {
            "aa": 11,
            "bb": 22
        }

 


免責聲明!

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



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