4 权限组件、频率、3组件总结

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

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

1、权限组件

1. 源码

1.权限函数

4 权限组件、频率、3组件总结

4 权限组件、频率、3组件总结

4 权限组件、频率、3组件总结

2.API settings配置

 4 权限组件、频率、3组件总结

3.核心代码 

View下的 self,代表view

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

4 权限组件、频率、3组件总结

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

 user表

4 权限组件、频率、3组件总结

数据库迁移与生成

4 权限组件、频率、3组件总结

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

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

    权限用到认证中的信息

 4 权限组件、频率、3组件总结

utils

4 权限组件、频率、3组件总结

 view

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

4 权限组件、频率、3组件总结

 test

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

4 权限组件、频率、3组件总结

4 权限组件、频率、3组件总结

 切换超级用户登录

4 权限组件、频率、3组件总结

4 权限组件、频率、3组件总结

4. 全局配置

通过权限认证  true

没有通过 false

 4 权限组件、频率、3组件总结

test

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

4 权限组件、频率、3组件总结

4 权限组件、频率、3组件总结

5. Code与Question

 Question1

books 先auth一下,才有request.name

不然都是,

 4 权限组件、频率、3组件总结

 Question 2

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

4 权限组件、频率、3组件总结4 权限组件、频率、3组件总结

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、核心代码

4 权限组件、频率、3组件总结

 4 权限组件、频率、3组件总结

4 权限组件、频率、3组件总结

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

ip   time

 4 权限组件、频率、3组件总结

4 权限组件、频率、3组件总结

3.request里面有什么内容

请求头

客户端的ip

通过什么都不做

不拖过才返回错误信息

4 权限组件、频率、3组件总结

 4 权限组件、频率、3组件总结

请求头必会的

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

相关推荐