zoukankan      html  css  js  c++  java
  • 4 权限组件、频率、3组件总结

    https://www.cnblogs.com/yuanchenqi/articles/8719520.html

    https://www.cnblogs.com/alice-bj/p/9252207.html#_label3

    1、权限组件

    1. 源码

    1.权限函数

    2.API settings配置

     

    3.核心代码 

    View下的 self,代表view

    ‘message’ 为认证错误返回的信息

    3.  需求:不是vip,不能看author

     user表

    数据库迁移与生成

    我要知道这次的请求人是谁

        在auth认证组件中中里面有 user

        权限用到认证中的信息

     

    utils

     view

        utils里的 类  和 view里的实例对象,必须一致

     test

     通过了第一层的认证,没有通过第二次的权限

     切换超级用户登录

    4. 全局配置

    通过权限认证  true

    没有通过 false

     

    test

    任何页面都需要权限才能访问

    5. Code与Question

     Question1

    books 先auth一下,才有request.name

    不然都是,

     

     Question 2

    auth的全局配置会影响login页面

    code 

    models

    from django.db import models
    
    # Create your models here.
    
    
    class User(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        type_choices = ((1,"普通用户"),(2,'SVip'),(3,'SSVip'))
        user_type = models.IntegerField(choices=type_choices,default=1)

    views

    # Author
    from .models import Author
    
    from app01.serilizer import AuthorModelSerializers
    from rest_framework import viewsets
    
    from app01.utils import SVipPermission
    
    class AuthorView(viewsets.ModelViewSet):
        # authentication_classes = [TokenAuth]   # 加上这个,走自己的认证,也就是不认证
                                      # 不加的话,自己没有,走全局的认证
        permission_classes = [SVipPermission,]
    
        # list数据            # create数据              # 继承APIView
        queryset = Author.objects.all()  # queryset,serilizers 名称不能修改
        serializer_class = AuthorModelSerializers

    utils

    from .models import User
    
    class SVipPermission(object):
        message = "只有超级用户才能访问"
        def has_permission(self,request,view):
            username = request.user
            print(username)
            user_type = User.objects.filter(name=username).first().user_type  # 对象直接 . 自己的属性
            if user_type == 3:
                return True  # 通过权限认证,可以看author表
            else:
                return False

    settings

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'],
        # 'DEFAULT_PERMISSION_CLASSES':['app01.utils.SVipPermission']
    }

    2. 频率组件

    1、核心代码

     

    2. 要求访问站点的频率不能超过每分钟20次

    ip   time

     

    3.request里面有什么内容

    请求头

    客户端的ip

    通过什么都不做

    不拖过才返回错误信息

     

    请求头必会的

    refer

    useraget

    contentype

    4. 全局配置

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'],
        'DEFAULT_PERMISSION_CLASSES':['app01.utils.SVipPermission'],
        'DEFAULT_THROTTLE_CLASSES':['app01.utils.VisitRateThrottle'],
        'DEFAULT_THROTTLE_RATES':{
            'visit_rate':'1/m'
        }
    }

    5.局部配置

     utils

    from rest_framework.throttling import BaseThrottle
    
    VISIT_RECORD={}
    class VisitThrottle(BaseThrottle):
    
        def __init__(self):
            self.history=None
    
        def allow_request(self,request,view):
            remote_addr = request.META.get('REMOTE_ADDR')
            print(remote_addr)
            import time
            ctime=time.time()
    
            if remote_addr not in VISIT_RECORD:
                VISIT_RECORD[remote_addr]=[ctime,]
                return True
    
            history=VISIT_RECORD.get(remote_addr)
            self.history=history
    
            while history and history[-1]<ctime-60:
                history.pop()
    
            if len(history)<3:
                history.insert(0,ctime)
                return True
            else:
                return False
    
        def wait(self):
            import time
            ctime=time.time()
            return 60-(ctime-self.history[-1])

    view

    from app01.service.throttles import *
    
    class BookViewSet(generics.ListCreateAPIView):
        throttle_classes = [VisitThrottle,]
        queryset = Book.objects.all()
        serializer_class = BookSerializers

    3. 三大组件总结

     1.笔记

    3 def dispatch():
          #一 初始化操作
          # (1) 构建新的request:
          self.request=self.initial_request()
          # self.request._request
          # self.request.GET
          # self.request.data
          # (2) 执行组件
          # 认证,权限,频率
          # 认证:request.user
          self.initial(request, *args, **kwargs)
                     ====   # 认证组件
                            self.perform_authentication(request)
                               ==== request.user
                                         ===== 
                                              for authenticator in self.authenticators:  # [TokenAuth(),]
                                                        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
                            
                            
                            # 权限组件
                            self.check_permissions(request)
                               ===========
                                     for permission in self.get_permissions():
                                            if not permission.has_permission(request, self):
                                                self.permission_denied(
                                                    request, message=getattr(permission, 'message', None)
                                                )
                            
                            
                            # 频率组件
                            self.check_throttles(request)
                            
                              =============
                                for throttle in self.get_throttles():  # [VisitRateThrottle(),]
                                        if not throttle.allow_request(request, self):
                                            self.throttled(request, throttle.wait()) # 受限制
                           
                            
           # 分发
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self,request.method.lower(),
                                      self.http_method_not_allowed)
            
                response = handler(request, *args, **kwargs)
                
                return response

    2.代码

    urls

    """restdemo URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/2.2/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  path('', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    """
    from django.contrib import admin
    from django.urls import path
    from django.urls import re_path  # 正则表达式的
    
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
    
        path('publishes/', views.PublishView.as_view()), # view(request)====> APIView:dispatch()
        re_path(r'publishes/(?P<pk>d+)/$', views.PublishDetailView.as_view(),name="detailPublish"),
    
        path('books/', views.BookView.as_view()),
        re_path(r'books/(d+)/$', views.BookDetailView.as_view()),
    
        # path('authors/', views.AuthorView.as_view()),
        # re_path(r'authors/(?P<pk>d+)/$', views.AuthorDetailView.as_view()),
    
    
        path('authors/', views.AuthorView.as_view({"get":"list","post":"create"}),name="book_list"),
        re_path(r'authors/(?P<pk>d+)/$', views.AuthorView.as_view({
                "get": "retrieve",
                "put": "update",
                "patch": "partial_update",
                "delete": "destroy"
                }),name="book_detail"),
    
        path('login/',views.LoginView.as_view())
    ]
    View Code

    models

    from django.db import models
    
    # Create your models here.
    
    
    class User(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        type_choices = ((1,"普通用户"),(2,'SVip'),(3,'SSVip'))
        user_type = models.IntegerField(choices=type_choices,default=1)
    
    class Token(models.Model):
        user = models.OneToOneField("user",on_delete=models.CASCADE)
        token = models.CharField(max_length=128)
        def __str__(self):
            return self.token
    
    class Book(models.Model):
        title=models.CharField(max_length=32)
        price=models.IntegerField()
        pub_date=models.DateField()
        publish=models.ForeignKey("Publish",on_delete=models.CASCADE)
        authors=models.ManyToManyField("Author")
        def __str__(self):
            return self.title
    
    
    class Publish(models.Model):
        name=models.CharField(max_length=32)
        email=models.EmailField()
        def __str__(self):
            # return self.name
            return self.email
    
    
    class Author(models.Model):
        name=models.CharField(max_length=32)
        age=models.IntegerField()
        def __str__(self):
            return self.name
    View Code

    views

    from django.shortcuts import render,HttpResponse
    
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from app01.serilizer import BookModelSerializers  # 从serilizer中导入
    from app01.serilizer import PublishModelSerializers
    
    
    from .models import Book,Publish
    
    
    class PublishView(APIView):   # APIView
        def get(self,request):
            publish_list = Publish.objects.all()
            ps = PublishModelSerializers(publish_list,many=True)
            return Response(ps.data)
    
        def post(self,request):
            ps = PublishModelSerializers(data=request.data)
            if ps.is_valid():
                ps.save()
                return Response(ps.data)
            else:
                return Response(ps.errors)
    
    
    class PublishDetailView(APIView):
        def get(self,request,pk):
            # 获取某publish的信息
            publish = Publish.objects.filter(pk=pk).first()
            ps = PublishModelSerializers(publish)
            return Response(ps.data)
    
        def put(self,request,pk):
            # 更新某pub的信息
            publish = Publish.objects.filter(pk=pk).first()
            ps = PublishModelSerializers(publish,data=request.data)
            if ps.is_valid():
                ps.save()
                return Response(ps.data)
            else:
                return Response(ps.errors)
    
        def delete(self,request,pk):
            # 删除某天publish
            Publish.objects.filter(pk=pk).delete()
            return Response("Delete 第%s个出版社"%(pk))
    
    
    from app01.utils import TokenAuth
    class BookView(APIView):
        authentication_classes = [TokenAuth,]  # 认证组件
        # permission_classes =[]  # 权限组件
        # throttle_classes = []  # 频率组件
    
        def get(self,request):
            print("request_user",request.user)
            print("request_auth",request.auth)
            book_list = Book.objects.all()
            bs = BookModelSerializers(book_list,many=True,context={'request':request})
            return Response(bs.data)  # Response继承HttpResponse
    
        def post(self,request):
            # post请求的数据
            bs = BookModelSerializers(data=request.data,context={'request':request})
            if bs.is_valid():
                print(bs.validated_data)
                bs.save()  # create方法
                return Response(bs.data)
            else:
                return Response(bs.errors)
    
    
    class BookDetailView(APIView):
        def get(self,request,id):
            # 获取某本书的信息
            book = Book.objects.filter(pk=id).first()  # 过滤单挑data
            bs = BookModelSerializers(book,context={'request':request})
            return Response(bs.data)
    
        def put(self,request,id):
            # 更新某本书的字段
            book = Book.objects.filter(pk=id).first()
            bs = BookModelSerializers(book,data=request.data,context={'request':request})
            if bs.is_valid():
                bs.save()  # 实质create方法
                return Response(bs.data)
            else:
                return Response(bs.errors)
    
        def delete(self,request,id):
            # 删除某条数据
            Book.objects.filter(pk=id).delete()
            return Response("Delete 第%s本书成功"%(id))
    
    
    
    # Author
    # 方法3:ModelViewSet
    from .models import Author
    
    from app01.serilizer import AuthorModelSerializers
    from rest_framework import viewsets
    
    from app01.utils import SVipPermission
    # from app01.utils import VisitRateThrottle
    class AuthorView(viewsets.ModelViewSet):
        # authentication_classes = [TokenAuth]   # 加上这个,走自己的认证,也就是不认证
                                      # 不加的话,自己没有,走全局的认证
        # permission_classes = [SVipPermission,]
        # throttle_classes = [VisitRateThrottle,]
    
        # list数据            # create数据              # 继承APIView
        queryset = Author.objects.all()  # queryset,serilizers 名称不能修改
        serializer_class = AuthorModelSerializers
    
    
    
    from .models import User,Token
    import json
    class LoginView(APIView):
        def get(self,request):
    
            return Response('login........')
        def post(self,request):
            print(1111)
            name = request.data.get('name')
            pwd = request.data.get('pwd')
            user = User.objects.filter(name=name,pwd=pwd).first()
            res = {'state_code':1000,'msg':None}
            if user:
                random_str = get_random_str(user.name)
                Token.objects.update_or_create(user=user,defaults={"token":random_str})
                res['token'] = random_str
    
            else:
                res['state_code'] = 1001 # 错误状态码
                res['msg'] = "用户名或者密码错误"
    
            return Response(json.dumps(res,ensure_ascii=False))  # 中文转义
    
    
    import hashlib
    import time
    
    def get_random_str(user):
        """md5加密"""
        ctime = str(time.time())
        md5 = hashlib.md5(bytes(user,encoding='utf8'))  # user加盐
        md5.update(bytes(ctime,encoding='utf8'))
    
        return md5.hexdigest()
    View Code

    utils

    from .models import User
    
    class SVipPermission(object):
        message = "只有超级用户才能访问"
        def has_permission(self,request,view):
            username = request.user
            print(username)
            user_type = User.objects.filter(name=username).first().user_type  # 对象直接 . 自己的属性
            if user_type == 3:
                return True  # 通过权限认证,可以看author表
            else:
                return False
    
    
    # 全局登录认证
    from .models import Token
    
    from rest_framework import exceptions
    from rest_framework.authentication import BaseAuthentication
    
    class TokenAuth(BaseAuthentication):
        def authenticate(self,request):
            token = request.GET.get("token")
            token_obj = Token.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed("验证失败")
            return (token_obj.user.name,token_obj.token)
    
        def authenticate_header(self,request):  # 暂时不用管
            pass
    
    
    '''
    
    class VisitRateThrottle(object):
        def allow_request(self,request,view):
            # 要求访问站点的频率不能够超过每分钟20次
    
            if 1:
                print(request.META.get("REMOTE_ADDR"))
                return True
            else:
                return False
    
    
    from rest_framework.throttling import BaseThrottle
    
    VISIT_RECORD={}
    class VisitThrottle(BaseThrottle):
    
        def __init__(self):
            self.history=None
    
        def allow_request(self,request,view):
            remote_addr = request.META.get('REMOTE_ADDR')
            print(remote_addr)
            import time
            ctime=time.time()
    
            if remote_addr not in VISIT_RECORD:
                VISIT_RECORD[remote_addr]=[ctime,]
                return True
    
            history=VISIT_RECORD.get(remote_addr)
            self.history=history
    
            while history and history[-1]<ctime-60:
                history.pop()
    
            if len(history)<3:
                history.insert(0,ctime)
                return True
            else:
                return False
    
        def wait(self):
            import time
            ctime=time.time()
            return 60-(ctime-self.history[-1])
    '''
    View Code

    settings

    STATIC_URL = '/static/'
    
    
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.TokenAuth'],
        'DEFAULT_PERMISSION_CLASSES':['app01.utils.SVipPermission'],
        'DEFAULT_THROTTLE_CLASSES':['app01.utils.VisitRateThrottle'],
        'DEFAULT_THROTTLE_RATES':{
            'visit_rate':'1/m'
        }
    }
    View Code
  • 相关阅读:
    浅谈表单同步提交和异步提交
    springboot多数据源&动态数据源(主从)
    MyBatis 中 @Param 注解的四种使用场景,最后一种经常被人忽略!
    手把手带你入门 Spring Security!
    10分钟了解JSON Web令牌(JWT)
    什么是Http无状态?Session、Cookie、Token三者之间的区别
    彻底理解cookie,session,token的区别
    56.合并区间(面试遇到的一道算法题,简述解法)
    C#object
    职称考试整理
  • 原文地址:https://www.cnblogs.com/venicid/p/11291464.html
Copyright © 2011-2022 走看看