django-rest-framework 基础三 认证、权限和频率


django-rest-framework 基础三 认证、权限和频率

1. 认证

登录接口: 登录成功只要给前端返回json格式字符串,这个字符串中带一个随机字符串(可以使用uuid生成)

登录接口步骤:

前端传入用户名和密码,然后去user表中查找,能找到说明用户和密码没问题,登录成功,然后在userToken表中存一条记录,说明登录过了,再返回前端一个json字符串 

1.1 登录接口

models.py

from django.db import models  # Create your models here.  class User(models.Model):     username = models.CharField(max_length=64)     password = models.CharField(max_length=128)     user_type = models.IntegerField(choices=((1, "超级管理员"),(2,"管理员"),(3,"普通用户")))  class UserToken(models.Model):     user = models.OneToOneField(to=User,on_delete=models.CASCADE)     userToken = models.CharField(max_length=64)   

views.py

from django.shortcuts import render  # Create your views here. from rest_framework.viewsets import GenericViewSet from authenticated.models import User,UserToken from rest_framework.response import Response from rest_framework.decorators import action import uuid  class UserView(GenericViewSet):      @action(methods=['POST'], detail=False)     def login(self,request):         username = request.data.get("username")         password = request.data.get("password")         user = User.objects.filter(username=username, password=password).first()          if not user:             return  Response({"code":1001,"msg":"用户名或密码错误"})          token = str(uuid.uuid4())  # 获取一个不重复的值,做唯一标识         # userToken表中有就更新,没有就创建         #UserToken.objects.update_or_create(user=user, defaults={'token': token})         UserToken.objects.update_or_create(user=user, defaults={'userToken': token})         # 返回信息,并带着token         return Response({"code":1000,"msg":"登录成功",'userToken': token})   

urls.py

from django.contrib import admin from django.urls import path,include from authenticated import views from rest_framework import routers  router = routers.SimpleRouter() router.register('user',views.UserView, "user")  urlpatterns = [     path('admin/', admin.site.urls),     path('', include(router.urls)) ] 

访问:

post请求: http://127.0.0.1:8000/user/login/ 

1.2 认证

有了登录接口,就可以实现认证,如果要调用别的接口必须要先登录才可以。

例如有个图书的表有五个接口,要访问图书的五个接口必须就登录。

步骤:

1. 先写一个类,继承BaseAuthentication,并重写authenticate方法,在方法中校验是否登录,登录则返回两个值,没有则拋异常 from rest_framework.authentication import BaseAuthentication class xxxx(BaseAuthentication): 	def authenticate(self, request):          2.  全局配置和局部配置 全局配置: settings.py中     REST_FRAMEWORK = {     "DEFAULT_AUTHENTICATION_CLASSES":["authenticated.authentication.LoingAuth"] } 局部配置: 在视图类中: authentication_classes = [xxxx,]  禁止局部署配置: authentication_classes = []   登录则返回两个值:     request.user 当前登录的用户     request.auth 为当前登录用户的token 

示例:

models.py

from django.db import models  # Create your models here.  class User(models.Model):     username = models.CharField(max_length=64)     password = models.CharField(max_length=128)     user_type = models.IntegerField(choices=((1, "超级管理员"),(2,"管理员"),(3,"普通用户")))  class UserToken(models.Model):     user = models.OneToOneField(to=User,on_delete=models.CASCADE)     userToken = models.CharField(max_length=64)   class Book(models.Model):     name = models.CharField(max_length=64)     price = models.DecimalField(max_digits=5, decimal_places=2)     author = models.CharField(max_length=64) 

认证功能,在app中新建authentication.py

from rest_framework.authentication import BaseAuthentication from authenticated.models import  UserToken from rest_framework.exceptions import AuthenticationFailed  class LoingAuth(BaseAuthentication):     def authenticate(self, request):         token = request.query_params.get('token')         user_token = UserToken.objects.filter(userToken=token).first()         if not user_token:             raise AuthenticationFailed("请先登录")         return user_token.user, token  

views.py

from django.shortcuts import render  # Create your views here. from rest_framework.viewsets import GenericViewSet from authenticated.models import User,UserToken from rest_framework.response import Response from rest_framework.decorators import action import uuid   from rest_framework.viewsets import ModelViewSet from authenticated.models import Book from authenticated.serializer import BookSerializer from authenticated.authentication import LoingAuth  class UserView(GenericViewSet):      @action(methods=['POST'], detail=False)     def login(self,request):          username = request.data.get("username")         password = request.data.get("password")         user = User.objects.filter(username=username, password=password).first()          if not user:             return  Response({"code":1001,"msg":"用户名或密码错误"})          token = str(uuid.uuid4())         # userToken表中有就更新,没有就创建         #UserToken.objects.update_or_create(user=user, defaults={'token': token})         UserToken.objects.update_or_create(user=user, defaults={'userToken': token})         return Response({"code":1000,"msg":"登录成功",'token': token})    class BookView(ModelViewSet):     # 只对BookView单独进行认证(局部配置)     authentication_classes = [LoingAuth,]     queryset = Book.objects.all()     serializer_class = BookSerializer 

路由urls.py

from django.contrib import admin from django.urls import path,include from authenticated import views from rest_framework import routers  router = routers.SimpleRouter() router.register('user',views.UserView, "user") router.register('books', views.BookView,"books")  urlpatterns = [     path('admin/', admin.site.urls),     path('', include(router.urls)) ] 

全局配置settings.py

REST_FRAMEWORK = {     "DEFAULT_AUTHENTICATION_CLASSES":["authenticated.authentication.LoingAuth"], } # authenticated.authentication.LoingAuth 为写的认证的类 # 全局配置后局部配置的就可以取消了。 # 但是全局配置后如果有些类不想让它有认证,比如登录接口,它不能有认证否则就死循环了。  # 全局配置后,单独取消某一个接口的认证:  class UserView(ViewSet): 	authentication_classes = []  # 让它等于空就可以了。 

2. 权限

所有的接口必须登录后才能访问(给每个视图加认证),登录成功后如果是普通用户则只可查看全部或单条数据。如果想要增删改必须是管理员或超级管理员。

演示可以把五个接口写成两个视图:

在应用目录下创建permission.py文件

permission.py

from rest_framework.permissions import BasePermission   class userPermission(BasePermission):     def has_permission(self, request, view):         user_type = request.user.user_type         # (1, "超级管理员"),(2,"管理员"),(3,"普通用户"),如果小于3说明是管理或超管用户         if user_type <3:             return True         else:             return False 

视图views.py

from rest_framework.viewsets import GenericViewSet from authenticated.models import User, UserToken from authenticated.models import Book from authenticated.serializer import BookSerializer from authenticated.authentication import LoingAuth from rest_framework.mixins import CreateModelMixin, ListModelMixin, DestroyModelMixin, UpdateModelMixin,      RetrieveModelMixin       #用户登录接口此处省略(见上面1.2认证)           # 查看全部和单条。只要登录了谁都可以访问 class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin):     authentication_classes = [LoingAuth, ]     queryset = Book.objects.all()     serializer_class = BookSerializer   #  只有管理和超管用户可以 创建、修改、新增  from authenticated.permission import userPermission   class BookDetailView(GenericViewSet, CreateModelMixin, UpdateModelMixin, DestroyModelMixin):     authentication_classes = [LoingAuth]     permission_classes = [userPermission]     queryset = Book.objects.all()     serializer_class = BookSerializer  

路由 urls.py:

from django.contrib import admin from django.urls import path,include from authenticated import views from rest_framework import routers  router = routers.SimpleRouter() router.register('user',views.UserView, "user") router.register('books', views.BookView,"books") router.register('bookdetail', views.BookDetailView,"bookdetail")  urlpatterns = [     path('admin/', admin.site.urls),     path('', include(router.urls)) ] 

全局配置settings.py

REST_FRAMEWORK = {    "DEFAULT_PERMISSION_CLASSES":["authenticated.permission.userPermission"], } # authenticated.permission.userPermission 为写的权限的类 # 全局配置后局部配置的就可以取消了。  # 全局配置后,单独取消某一个接口的权限:  class UserView(ViewSet): 	permission_classes = []  # 让它等于空就可以了。 

普通用户访问的时候会报没有权限

django-rest-framework 基础三 认证、权限和频率

2.1 权限总结:

两个视图:

BookView:获取所有,获取单条  BookDetailView:删除,修改,新增 上面两个视图都需要登录:authentication_classes = [LoginAuth, ]  BookDetailView必须有权限才能,加了一个权限,permission_classes = [UserPermission, ] 

编写权限步骤

第一步:写一个类,继承BasePermission,重写has_permission,判断如果有权限,返回True,如果没有权限,返回False 第二步:局部配置和全局配置 局部配置 		class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin):     		permission_classes = [UserPermission, ]      全局配置     settings.py   		REST_FRAMEWORK={ 			"DEFAULT_PERMISSION_CLASSES":["authenticated.permission.userPermission",] 		} 

3. 频率

限制访问的频率

在应用目录创建throttle.py文件用来限制频率

throttle.py

from rest_framework.throttling import SimpleRateThrottle  class IpThrottle(SimpleRateThrottle):     scope = 'min_3'   # 在settings.py定义给哪个类限制的频率      # get_cache_key 返回什么就以什么做限制,现在是以IP做限制     def get_cache_key(self, request, view):         return request.META.get('REMOTE_ADDR')  # 返回的是客户端的IP,以IP做限制     	# return request.user.id # 返回已经登录的用户的id,以用户id做限制 

views.py

from authenticated.throttle import IpThrottle  # 查看全部和单条。只要登录了谁都可以访问 class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin):     authentication_classes = [LoingAuth, ]     throttle_classes = [IpThrottle]  # 访问BookView类做限制     queryset = Book.objects.all()     serializer_class = BookSerializer 

settings.py

REST_FRAMEWORK = {     "DEFAULT_THROTTLE_RATES":{         'min_3':'3/m',       }, }  # min_3 就是上面throttle.py.IpThrottle里scope定义的,这个一定要和scope定义的一致 # 3/m 每一分钟访问3次 ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day') # 如果throttle.py.IpThrottle里还有别的限制的类,如果scope也是为min_3,那它也是每分钟访问3次的限制 

超过3次就会报错:

django-rest-framework 基础三 认证、权限和频率

上面的配置为局部配置,也可以设置全局配置

settings.py

REST_FRAMEWORK = {    "DEFAULT_THROTTLE_CLASSES" : ["authenticated.throttle.IpThrottle"], # 全局配置     "DEFAULT_THROTTLE_RATES":{          'min_3':'3/m',     }, } # 同样设置了全局,局部的throttle_classes = [IpThrottle]就可以不写了 # 如果只是某个类禁用: throttle_classes = [] 

3.1 频率总结

步骤:

第一步:写一个类,继承SimpleRateThrottle,重写类属性:scope,和get_cache_key方法   	get_cache_key返回什么,就以什么做限制,     scope配置文件中要用      第二步:在配置文件中配置 settings.py中 REST_FRAMEWORK = {     "DEFAULT_THROTTLE_RATES":{         'min_3':'3/m',  # minute_3是scope的字符串,一分钟访问3次     }, }  第三步: 使用 1. 局部使用--》视图类中   class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin):     throttle_classes = [IPThrottle]       2. 全局使用--配置文件中 settings.py中 REST_FRAMEWORK = {     "DEFAULT_THROTTLE_CLASSES" : ["authenticated.throttle.IpThrottle"],     "DEFAULT_THROTTLE_RATES":{         'min_3':'3/m',  # minute_3是scope的字符串,一分钟访问3次     }, } 
发表评论

相关文章