drf -三大权限认证例子
三大权限认证测试例子代码
models.py
from django.db import models
# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.CharField(max_length=32)
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
# user_type区分是什么类型用户:超级管理员 1,普通用户 2, 2b用户 3
user_type = models.IntegerField(default=3, choices=((1, '超级管理员'), (2, '普通用户'), (3, '2b用户')))
# 其实choice本质就是有关联,后期不会修改的情况下使用choice,后期会增加或减少用户类型的情况下,要使用另一个表
# user_type = models.IntegerField(default=1)
#外键关联
def __str__(self):
return self.username
# 用户登录记录表
# 如何区分用户是否登录了?
class UserToken(models.Model):
# SET_NULL SET_DEFAULT CASCADE SET(函数内存地址)
# 用户如果没有登录,就是空,如果登录了,就有值,登录多次以最后一次为准
user = models.OneToOneField(to='User', on_delete=models.CASCADE)
token = models.CharField(max_length=32, null=True)
pycharm ->tools-run manage.py
makemigration ->migrate
urls.py
from django.contrib import admin
from django.urls import path, include
from app01 import views
from rest_framework.routers import DefaultRouter, SimpleRouter
# 自动生成路由
# drf提供了两个路由类,以后继承了ViewSetMixin及其子类的视图类,就可以使用这两个路由类来自动生成路由
# 第一步:导入路由类
# 第二步实例化对象
router = SimpleRouter()
# 第三步:注册路由(注册多个)
# 第一个参数:路径 第二个参数:视图类 第三个参数:别名,可以不写
router.register('user', views.UserView, 'user')
router.register('books', views.BookView, 'books')
router.register('publish', views.PublishView, 'publish')
## 第四步:把自动生成的路由添加到urlpatterns中
# 第四步
urlpatterns = [
path('admin/', admin.site.urls),
# 方式一
path('', include(router.urls)),
]
views.py
from django.shortcuts import render
from rest_framework.views import APIView
from .models import Book, Publish
from rest_framework.viewsets import ViewSetMixin, ViewSet, GenericViewSet, ModelViewSet, ReadOnlyModelViewSet
from .serializer import BookSerializer, PublishSerializer
from rest_framework.response import Response
from rest_framework.decorators import action
from .models import User, UserToken
import uuid
class BookView(ModelViewSet):
serializer_class = BookSerializer
queryset = Book.objects.all()
class PublishView(ModelViewSet):
# 关闭登录认证
authentication_classes = []
# 关闭权限认证
permission_classes = []
serializer_class = PublishSerializer
queryset = Publish.objects.all()
def list(self, request, *args, **kwargs):
# self:是视图类的对象
print(request.user)
print(request.auth)
return super().list(request, *args, **kwargs)
class UserView(ViewSet):
# 关闭登录验证
authentication_classes = []
# 关闭访问权限认证
permission_classes = []
@action(methods=['POST', ], detail=False, url_path='login')
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username, password=password).first()
if user:
token = str(uuid.uuid4()) # 生成一个随机字符串
UserToken.objects.update_or_create(defaults={'token': token}, user=user)
return Response({'code': 100, 'msg': '登录成功', 'token': token})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
新建auth,permission,throttling
auth.py:写登录认证类
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01.models import UserToken
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
print(request.META)
# 在这里做认证,校验用户是否登录(带了token,并且能查到,就是登录,返回两个值,否则就是没登录,抛异常)
# 用户带的token从哪取?后端人员定的:放在请求地址中
# token = request.GET.get('token')
login_token = request.GET.get('token')
# 通过什么验证呢?我们有token.还有什么?
# 通过token查询该token是否是在表中有记录
token_data = UserToken.objects.filter(token=login_token).first()
if token_data:
# 返回两个值,一个是当前登录用户,一个是token
return token_data.user, login_token
else:
raise AuthenticationFailed('您未登录')
permission.py:权限认证类
from rest_framework.permissions import BasePermission
class UserTypePermission(BasePermission):
def has_permission(self, request, view):
if request.user.user_type == 1:
return True
else:
# self.message = '普通用户和2b用户都没有权限' # 返回给前端的提示是什么样
# 使用了choice后,user.user_type 拿到的是数字类型,想变成字符串 user.get_user_type_display()
self.message = '您是:%s 用户,您没有权限' % request.user.get_user_type_display()
return False
throttling.py: 访问频率类
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
class MyThrottling(SimpleRateThrottle): # 我们继承SimpleRateThrottle去写,而不是继承BaseThrottle去写
# 类属性,这个类属性可以随意命名,但要跟配置文件对应
scope = 'diga'
def get_cache_key(self, request, view):
# 返回什么,频率就以什么做限制
# 可以通过用户id限制
# 可以通过ip地址限制
return request.META.get('REMOTE_ADDR')
settings.py
#开启登录认证,权限认证
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['app01.auth.LoginAuth', ],
'DEFAULT_PERMISSION_CLASSES': ['app01.permission.UserTypePermission'],
'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.MyThrottling'],
'DEFAULT_THROTTLE_RATES': {
'diga': '3/m'
}
}