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 }