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 }
