DRF(五)

一.权限机制

        基于权限的认证
        基于角色的认证:
                  RBAC(Role-Based Access Control)

                  Django采用六表:

二.自定义User表

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(可以登录后台管理系统的用户)

 

原文地址:https://www.cnblogs.com/sima-3/p/11483921.html