DRF(五)
一.权限机制
基于权限的认证
基于角色的认证:
RBAC(Role-Based Access Control)
Django采用六表:
models.py:
from django.db import models class Car(models.Model): name = models.CharField(max_length=64) is_delete = models.BooleanField(default=0) class Meta: db_table = 'old_boy_car' verbose_name = '汽车' verbose_name_plural = verbose_name def __str__(self): return self.name from django.contrib.auth.models import AbstractUser class User(AbstractUser): mobile = models.CharField(max_length=11) class Meta: db_table = 'old_boy_user' verbose_name = '用户' verbose_name_plural = verbose_name def __str__(self): return self.username
settings.py:
# 配置自定义User表
AUTH_USER_MODEL = 'api.user'
后台注册:
from django.contrib import admin from . import models admin.site.register(models.Car) admin.site.register(models.User) 此时user不再是系统的user,需要注册
在测试文件中进行六表orm操作:
import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dg_proj.settings") import django django.setup() """ 相互访问 User: groups user_permissions Group:user_set permissions Permission:user_set group_set """ from api.models import User from django.contrib.auth.models import Group from django.contrib.auth.models import Permission user = User.objects.get(pk=2) # type: User print(user.username) print(user.groups.first().name) print(user.user_permissions.first()) group = Group.objects.get(pk=1) print(group) print(group.user_set.get(pk=2)) print(group.permissions.get(pk=1)) permission = Permission.objects.get(pk=19) 跟user有关 print(permission) print(permission.user_set.first()) permission = Permission.objects.get(pk=1) 跟group有关 print(permission.group_set.first())
三.需要认证访问的接口准备
a.主路由
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include('api.urls')), ]
b.路由分发
from django.conf.urls import url from . import views urlpatterns = [ # 用户的详情消息,只有在登录后才能查看 url(r'^users/(?P<pk>.*)/$', views.UserRetrieveAPIView.as_view()), # 游客只可以查看,登录后可以增删改 url(r'^cars/$', views.CarModelViewSet.as_view({ 'get': 'list', 'post': 'create' })), url(r'^cars/(?P<pk>.*)/$', views.CarModelViewSet.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy', })), ]
c.序列化类
from rest_framework import serializers from . import models class UserModelSerializer(serializers.ModelSerializer): class Meta: model = models.User fields = ('username', 'mobile') class CarModelSerializer(serializers.ModelSerializer): class Meta: model = models.Car fields = ('name',)
d.视图类
from rest_framework.generics import RetrieveAPIView from . import models, serializers class UserRetrieveAPIView(RetrieveAPIView): queryset = models.User.objects.filter(is_active=True) serializer_class = serializers.UserModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet class CarReadOnlyModelViewSet(ReadOnlyModelViewSet): queryset = models.Car.objects.filter(is_delete=False) serializer_class = serializers.CarModelSerializer
四.认证源码分析与session认证
1.入口:
2.找dispach方法:
3.找auth认证入口:
4.进入auth认证方法,返回request(封装后)的user方法
5.进入Request类找user
6.开始认证:
7.找Request实例化的认证属性,认证对象的赋值入口
8.认证赋值:
9.把rest_framwork的settings.py文件中有关认证的配置复制到自己的settings.py文件中:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ # django默认session校验:校验规则 游客 及 登录用户 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ] }
10.session校验登录用户和游客,找authentication.py文件的SessionAuthentication类:
def authenticate(self, request): """ Returns a `User` if the request session currently has a logged in user. Otherwise returns `None`. """ # Get the session-based user from the underlying HttpRequest object user = getattr(request._request, 'user', None) 游客不进行csrf校验 # Unauthenticated, CSRF validation not required if not user or not user.is_active: return None 登录用户进行csrf校验 self.enforce_csrf(request) # CSRF passed with authenticated user return (user, None)
可自定义携带校验信息但未通过的非法用户:
五.认证原理:
认证校验方法:
返回None => 游客
返回user,auth => 登录用户
抛出异常 => 非法用户
1)如果前台没有携带认证信息,直接定义为游客
2)如果前台携带了认证信息并认证通过,定位为登录用户,将登录的用户user对象保存在 requset.user 中
3)如果前台携带了认证信息但没有认证通过,一般都定义为游客
可以自定义为非法用户,抛出 认证失败 异常,但是不建议直接操作,可以交给权限组件进一步处理
rest_framework.exceptions 的 AuthenticationFailed
六.权限校验:
1. 找到步骤2,3进入权限入口:
2.进入权限赋值入口get_permissions
3.把rest_framwork的settings.py文件中有关权限的配置复制到自己的settings.py文件中(可找permissions.py):
# drf配置 """ AllowAny:允许所有用户 IsAuthenticated:只允许登录用户 IsAuthenticatedOrReadOnly:游客只读,登录用户无限制 IsAdminUser:是否是后台用户 """ REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', # 全局配置:一站式网站(所有操作都需要登录后才能访问) # 'rest_framework.permissions.IsAuthenticated', ], }
4.视图校验
from rest_framework.generics import RetrieveAPIView from . import models, serializers from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response #登录才能查看,游客不可查看 class UserRetrieveAPIView(RetrieveAPIView): # 局部配置 # 局部取消认证组件:authentication_classes = [] # 局部启用认证组件:authentication_classes = [认证类们] # 局部取消权限组件: permission_classes = [] # 局部启用权限组件: permission_classes = [权限类们] permission_classes = [IsAuthenticated] queryset = models.User.objects.filter(is_active=True) serializer_class = serializers.UserModelSerializer from rest_framework.viewsets import ModelViewSet # 游客只可以查看,登录后可以增删改 from rest_framework.permissions import IsAuthenticatedOrReadOnly class CarModelViewSet(ModelViewSet): queryset = models.Car.objects.filter(is_delete=False) serializer_class = serializers.CarModelSerializer permission_classes = [IsAuthenticatedOrReadOnly] def destroy(self, request, *args, **kwargs): obj = self.get_object() obj.is_delete = True obj.save() return Response('删除成功')
5.权限校验原理:
权限校验方法:
返回False => 没有权限,将信息返回给前台
返回True => 拥有权限,进行下一步认证(频率认证)
1)AllowAny:允许所有用户,校验方法直接返回True
2)IsAuthenticated:只允许登录用户
必须request.user和request.user.is_authenticated都通过
3)IsAuthenticatedOrReadOnly:游客只读,登录用户无限制
get、option、head 请求无限制
前台请求必须校验 request.user和request.user.is_authenticated
4)IsAdminUser:是否是后台用户
校验 request.user和request.user.is_staff is_staff(可以登录后台管理系统的用户)