day86

1 drf认证功能介绍
2 认证功能源码分析
3 自定义认证类(重点)
4 认证功能局部使用和全局使用
5 自定义权限功能(重点)
6 权限功能局部使用和全局使用
7 内置的权限和认证类
## 1 drf认证功能介绍

```python
0 认证,频率,权限
1 用户是否登录到系统中
2 后期基本上会用JWT的认证
3 自定制的认证
```



## 2 认证功能源码分析

```python
1 APIView---》dispatch---》self.initial(request, *args, **kwargs)--》self.perform_authentication(request)---》Request.user--->self._authenticate(self):Request类的方法---》self.authenticators:Request类的属性---》在Request对象实例化的时候传入的----》Request在什么时候实例化的?dispatch的时候---》APIView:self.get_authenticators()--》return [auth() for auth in self.authentication_classes]----》如果在自己定义的视图类中写了authentication_classes=[类1,类2]----》Request的self.authenticators就变成了我们配置的一个个类的对象
        
        
2 self._authenticate(self):Request类的方法
def _authenticate(self):
     for authenticator in self.authenticators: # BookView中配置的一个个类的对象
            try:
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:
                self._not_authenticated()
                raise

            if user_auth_tuple is not None:
                self._authenticator = authenticator
                self.user, self.auth = user_auth_tuple
                return
3 只要在视图类中配置authentication_classes = [MyAuthen.LoginAuth, ]
    就会执行上面的方法,执行认证

```



## 3 自定义认证类(重点)

```python
1 使用
    -定义一个类,继承BaseAuthentication
    class LoginAuth(BaseAuthentication):
        def authenticate(self, request):
            token = request.GET.get('token')
            res = models.UserToken.objects.filter(token=token).first()
            if res:
                return 元组
            else:
                raise AuthenticationFailed('您没有登录')
    -重写authenticate方法
    -局部使用和全局使用
        -局部:在视图类中配置(只要配置了,就是登录以后才能访问,没配置,不用登录就能访问)
            authentication_classes = [MyAuthen.LoginAuth, ]
        -全局
        REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": ["app01.MyAuthen.LoginAuth", ]
        }
        
   -注意:
    1 认证类,认证通过可以返回一个元组,有两个值,第一个值会给,request.user,第二个值会给request.auth
    2 认证类可以配置多个,按照从前向后的顺序执行,如果前面有返回值,认证就不再继续往下走了
```



## 4 认证功能局部使用和全局使用

```python
1 全局使用(所有接口,都需要登录才能访问)
    -在配置文件中
        REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": ["app01.MyAuthen.LoginAuth", ]
        }
2 局部使用
    -在想局部使用的视图类上
    authentication_classes = [MyAuthen.LoginAuth,]
3 局部禁用
    -在想禁用的视图类上
    authentication_classes = []
    

```







## 5 自定义权限功能(重点)

```python
1 登录成功以后,超级用户可以干某些事,普通用户不能干---》超级用户可以查看某些接口,普通用户不能查看


2 使用写一个类继承BasePermission,重写has_permission
    class SuperPermission(BasePermission):
        def has_permission(self, request, view):
            # Return `True` if permission is granted, `False` otherwise.
            # 超级用户可以访问,除了超级用户以外,都不能访问
            if request.user.user_type == '1':
                return True
            else:
                return False
            
3 局部使用和全局使用
    -在想局部使用的视图类上
    permission_classes = [MyAuthen.SuperPermission]
    -全局使用
      REST_FRAMEWORK = {
        "DEFAULT_PERMISSION_CLASSES": ["app01.MyAuthen.SuperPermission", ]
        }
     -局部禁用
    permission_classes = []
```



## 6 权限功能局部使用和全局使用

```python
1 使用方式
    -在想局部使用的视图类上
    permission_classes = [MyAuthen.SuperPermission]
    -全局使用
      REST_FRAMEWORK = {
        "DEFAULT_PERMISSION_CLASSES": ["app01.MyAuthen.SuperPermission", ]
        }
     -局部禁用
    permission_classes = []
```





## 7 内置的权限和认证类

```python
# 内置认证类
from rest_framework.exceptions import AuthenticationFailed
# 内置权限类
from rest_framework.permissions import BasePermission
```

 

my_authenticate.py

from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from app01 import models
from rest_framework.exceptions import AuthenticationFailed


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # token放到get请求的参数中或是请求头中
        token = request.GET.get('token')
        res = models.UserToken.objects.filter(token=token).first()
        if res:
            return (res.user, token)    # 返回一个元组(如果不返回用户对象,后面的权限认证就没有用户对象,只有匿名用户)
        else:
            raise AuthenticationFailed('没有登录无法访问')


class SuperPermission(BasePermission):
    message = '您没有访问权限'

    def has_permission(self, request, view):
        # user_type = request.user.user_type
        if request.user.user_type == 1:
            return True
        else:
            return False

 

views.py

from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from app01 import models
from rest_framework.response import Response
from app01 import my_authenticate
import uuid


class BookView(APIView):
    authentication_classes = [my_authenticate.LoginAuth, ]      # 局部使用认证
    permission_classes = [my_authenticate.SuperPermission, ]

    def get(self, request):
        return Response('获取了所有图书')


class PublishView(APIView):
    authentication_classes = []     # 局部禁用
    permission_classes = []

    def get(self, request):
        return Response('获取了所有出版社')


class LoginView(APIView):
    authentication_classes = []     # 局部禁用认证
    permission_classes = []
    def post(self, request):
        dic = {'code': 100, 'msg': '登录成功'}
        username = request.data.get('username')
        password = request.data.get('password')
        user = models.User.objects.filter(username=username, password=password).first()
        if user:
            token = uuid.uuid4()
            # 查询该用户是否存在对应的token,若存在,则更新;否则新增
            models.UserToken.objects.update_or_create(defaults={'token': token}, user=user)
            dic['token'] = token
            return Response(dic)
        else:
            dic['code'] = 101
            dic['msg'] = '用户名或密码错误'
            return Response(dic)

 

posted @ 2020-11-11 21:05  板鸭没有腿  阅读(137)  评论(0)    收藏  举报