04,认证权限频率

Posted pontoon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了04,认证权限频率相关的知识,希望对你有一定的参考价值。

 

认证组件

Django原生的authentic组件为我们的用户注册与登录提供了认证功能,十分的简介与强大。同样DRF也为我们提供了认证组件,一起来看看DRF里面的认证组件是怎么为我们工作的!
models.py
<wiz_code_mirror>
 
 
 
15
 
 
 
 
 
1
# 定义一个用户表和一个保存用户Token的表
2

3

4
class UserInfo(models.Model):
5
    username = models.CharField(max_length=16)
6
    password = models.CharField(max_length=32)
7
    type = models.SmallIntegerField(
8
        choices=((1, ‘普通用户‘), (2, ‘VIP用户‘)),
9
        default=1
10
    )
11

12

13
class Token(models.Model):
14
    user = models.OneToOneField(to=‘UserInfo‘)
15
    token_code = models.CharField(max_length=128)
 
 
url
<wiz_code_mirror>
 
 
 
1
 
 
 
 
 
1
    path(‘login/‘, views.LoginView.as_view()),
 
 
views.py
<wiz_code_mirror>
 
 
 
38
 
 
 
 
 
1
# 视图主要处理用户名、密码是否正确,用户每一次请求都要带着专有token来!
2
import hashlib, time
3
from rest_framework.response import Response
4
from rest_framework.views import APIView
5

6

7
def get_random_token(username):
8
    """
9
    根据用户名和时间戳生成随机token
10
    :param username:
11
    :return:
12
    """
13
    timestamp = str(time.time())
14
    m = hashlib.md5(bytes(username, encoding="utf8"))
15
    m.update(bytes(timestamp, encoding="utf8"))
16
    return m.hexdigest()
17

18

19
class LoginView(APIView):
20
    """
21
    校验用户名密码是否正确从而生成token的视图
22
    """
23
    def post(self, request):
24
        res = {"code": 0}
25
        print(request.data)
26
        username = request.data.get("username")
27
        password = request.data.get("password")
28

29
        user = models.UserInfo.objects.filter(username=username, password=password).first()
30
        if user:
31
            # 如果用户名密码正确
32
            token = get_random_token(username)
33
            models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)
34
            res["token"] = token
35
        else:
36
            res["code"] = 1
37
            res["error"] = "用户名或密码错误"
38
        return Response(res)
 
 
定义认证类model_serializer.py
<wiz_code_mirror>
 
 
 
18
 
 
 
 
 
1
# 这一步是要对着源码才能写出来
2
from rest_framework.authentication import BaseAuthentication
3
from rest_framework.exceptions import AuthenticationFailed
4

5

6
class MyAuth(BaseAuthentication):
7
    def authenticate(self, request):
8
        if request.method in ["POST", "PUT", "DELETE"]:
9
            request_token = request.data.get("token", None)
10
            if not request_token:
11
                raise AuthenticationFailed(‘缺少token‘)
12
            token_obj = models.Token.objects.filter(token_code=request_token).first()
13
            if not token_obj:
14
                raise AuthenticationFailed(‘无效的token‘)
15
            return token_obj.user.username, None
16
        else:
17
            return None, None
18

 
 
全局配置
<wiz_code_mirror>
 
 
 
4
 
 
 
 
 
1
# 在settings.py中配置
2
REST_FRAMEWORK = {
3
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
4
}
 
 
 

权限组件

只有vip才能看的内容
自定义权限类
<wiz_code_mirror>
 
 
 
15
 
 
 
 
 
1
# 自定义权限类
2
from rest_framework.permissions import BasePermission
3

4
class MyPermission(BasePermission):
5
    message = ‘VIP用户才能访问‘
6

7
    def has_permission(self, request, view):
8
        """
9
        自定义权限只有VIP用户才能访问
10
        """
11
        # 因为在进行权限判断之前已经做了认证判断,所以这里可以直接拿到request.user
12
        if request.user and request.user.type == 2:  # 如果是VIP用户
13
            return True
14
        else:
15
            return False
 
 
视图级别配置
<wiz_code_mirror>
 
 
 
6
 
 
 
 
 
1
class CommentViewSet(ModelViewSet):
2

3
    queryset = models.Comment.objects.all()
4
    serializer_class = app01_serializers.CommentSerializer
5
    authentication_classes = [MyAuth, ]
6
    permission_classes = [MyPermission, ]
 
 
全局配置
<wiz_code_mirror>
 
 
 
4
 
 
 
 
 
1
REST_FRAMEWORK = {
2
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
3
    "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
4
}
 
 
 

频率组件

频率:限制用户访问网站的频率
自定义限制类
<wiz_code_mirror>
 
 
 
33
 
 
 
 
 
1
VISIT_RECORD = {}
2
# 自定义限制
3
class MyThrottle(object):
4

5
    def __init__(self):
6
        self.history = None
7

8
    def allow_request(self, request, view):
9
        """
10
        自定义频率限制60秒内只能访问三次
11
        """
12
        # 获取用户IP
13
        ip = request.META.get("REMOTE_ADDR")
14
        timestamp = time.time()
15
        if ip not in VISIT_RECORD:
16
            VISIT_RECORD[ip] = [timestamp, ]
17
            return True
18
        history = VISIT_RECORD[ip]
19
        self.history = history
20
        history.insert(0, timestamp)
21
        while history and history[-1] < timestamp - 60:
22
            history.pop()
23
        if len(history) > 3:
24
            return False
25
        else:
26
            return True
27

28
    def wait(self):
29
        """
30
        限制时间还剩多少
31
        """
32
        timestamp = time.time()
33
        return 60 - (timestamp - self.history[-1])
 
 
视图级别配置
<wiz_code_mirror>
 
 
 
x
 
 
 
 
 
1
class CommentViewSet(ModelViewSet):
2

3
    queryset = models.Comment.objects.all()
4
    serializer_class = app01_serializers.CommentSerializer
5
    throttle_classes = [MyThrottle, ]
 
 
全局配置
<wiz_code_mirror>
 
 
 
 
 
 
 
 
 
1
# 在settings.py中设置rest framework相关配置项
2
REST_FRAMEWORK = {
3
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ],
4
    "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ]
5
    "DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ]
6
}
 
 
 
 
 
 


 

认证组件的源码阅读

源码、源码、源码!
技术分享图片
 
技术分享图片
 
技术分享图片
新构建的request里面的源码的user方法
技术分享图片
 
技术分享图片
 
技术分享图片
 
技术分享图片
 
 
源码走到了这里其实就已经需要我们自己来进行认证了。就可以对前端的请求进行认证,到底该怎么认证,还得继续往下走!
 
技术分享图片
 
技术分享图片
 
 
 
 
 

权限组件的源码阅读

技术分享图片
 
技术分享图片
 
技术分享图片
 
相比较与认证组件,权限组件就更加的简洁了
 

频率组件的注意部分

技术分享图片
 
 
 
 
 
 
 
 

以上是关于04,认证权限频率的主要内容,如果未能解决你的问题,请参考以下文章

drf认证权限频率

认证权限频率自定义签发token-多方式登录

Django REST框架--认证和权限

认证 权限 视图 频率

认证组件权限组件频率组件

REST framework (组件使用之认证权限访问频率)