# 认证的实现 1 写一个类,继承BaseAuthentication,重写authenticate,认证的逻辑写在里面,认证通过,返回两个值,一个值最终给了Requet对象的user,认证失败,抛异常:APIException或者AuthenticationFailed 2 全局使用,局部使用
models.py
from django.db import models # Create your models here. class Book(models.Model): name = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish = models.CharField(max_length=32) # ===========================认证用到的============================ class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) user_type = models.IntegerField(choices=((1, ‘超级用户‘), (2, ‘普通用户‘), (3, ‘二笔用户‘))) class UserToken(models.Model): token = models.CharField(max_length=64) user = models.OneToOneField(to=‘User‘, on_delete=models.CASCADE) # on_delete=models.CASCADE级联删除
app01/app_auth.py
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.models import UserToken class MyAuthentication(BaseAuthentication): def authenticate(self, request): # 认证逻辑,如果认证通过,返回两个值 # 如果认证失败,抛出AuthenticationFailed异常 token = request.GET.get(‘token‘) if token: user_token = UserToken.objects.filter(token=token).first() # 认证通过 if user_token: return user_token.user, token else: raise AuthenticationFailed(‘认证失败‘) else: raise AuthenticationFailed(‘请求地址中需要携带token‘)
views.py
from rest_framework.viewsets import ModelViewSet from rest_framework.views import APIView from app01.models import Book from app01.serializers import BookSerializer from rest_framework.decorators import action # 装饰器 from rest_framework.response import Response # ===============认证相关=========================== from app01.app_atuh import MyAuthentication from app01 import models import uuid # Create your views here. class BookViewSet(ModelViewSet): authentication_classes = [MyAuthentication, ] # 局部使用认证 queryset = Book.objects.all() serializer_class = BookSerializer @action(methods=[‘GET‘, ‘POST‘], detail=True) def get_1(self, request, pk): print(pk) book = self.get_queryset()[:1] # 从0开始截取一条 ser = self.get_serializer(book, many=True) return Response(ser.data) class LoginView(APIView): def post(self, request): username = request.data.get("username") password = request.data.get("password") user = models.User.objects.filter(username=username, password=password).first() if user: # 登录成功,生成随机字符串 token = uuid.uuid4() # 存到UserToken表中 # models.UserToken.objects.create(token=u_str, user=user) # 用它每次登录都会记录一条,不好, # update_or_create有就更新,没有就新增 models.UserToken.objects.update_or_create(defaults={‘token‘: token}, user=user) return Response({‘status‘: 200, ‘msg‘: ‘登录成功‘, ‘token‘: token}) else: return Response({‘status‘: 101, ‘msg‘: ‘用户名或密码错误‘})
urls.py
from django.contrib import admin from django.urls import path, re_path from app01 import views urlpatterns = [ path(‘admin/‘, admin.site.urls), path(‘login/‘, views.LoginView.as_view()), ] from rest_framework import routers router = routers.SimpleRouter() router.register(‘books‘, views.BookViewSet) # 不要加斜杠了 urlpatterns += router.urls
REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",] }
#局部使用,只需要在视图类里加入: authentication_classes = [TokenAuth, ]
原文:https://www.cnblogs.com/baicai37/p/13277207.html