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()) ]
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
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()
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]) '''
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' } }