# -*- coding: utf-8 -*- """ @author: 猿小天 @contact: QQ:1638245306 @Created on: 2021/6/2 002 14:20 @Remark:登录视图 """ import base64 import hashlib from datetime import datetime, timedelta from captcha.views import CaptchaStore, captcha_image from django.contrib import auth from django.contrib.auth import login from django.shortcuts import redirect from django.utils.translation import gettext_lazy as _ from drf_yasg import openapi from drf_yasg.utils import swagger_auto_schema from rest_framework import serializers from rest_framework.views import APIView from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework_simplejwt.views import TokenObtainPairView from application import settings from dvadmin.system.models import Users from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.validator import CustomValidationError class CaptchaView(APIView): authentication_classes = [] permission_classes = [] @swagger_auto_schema( responses={ '200': openapi.Response('获取成功') }, security=[], operation_id='captcha-get', operation_description='验证码获取', ) def get(self, request): hashkey = CaptchaStore.generate_key() id = CaptchaStore.objects.filter(hashkey=hashkey).first().id imgage = captcha_image(request, hashkey) # 将图片转换为base64 image_base = base64.b64encode(imgage.content) json_data = {"key": id, "image_base": "data:image/png;base64," + image_base.decode('utf-8')} return SuccessResponse(data=json_data) class LoginSerializer(TokenObtainPairSerializer): """ 登录的序列化器: 重写djangorestframework-simplejwt的序列化器 """ captcha = serializers.CharField(max_length=6, required=False, allow_null=True) class Meta: model = Users fields = "__all__" read_only_fields = ["id"] default_error_messages = { 'no_active_account': _('账号/密码不正确') } def validate(self, attrs): captcha = self.initial_data.get('captcha',None) if settings.CAPTCHA_STATE: if captcha is None: raise CustomValidationError("验证码不能为空") self.image_code = CaptchaStore.objects.filter( id=self.initial_data['captchaKey']).first() five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0) if self.image_code and five_minute_ago > self.image_code.expiration: self.image_code and self.image_code.delete() raise CustomValidationError('验证码过期') else: if self.image_code and (self.image_code.response == captcha or self.image_code.challenge == captcha): self.image_code and self.image_code.delete() else: self.image_code and self.image_code.delete() raise CustomValidationError("图片验证码错误") data = super().validate(attrs) data['name'] = self.user.name data['userId'] = self.user.id data['avatar'] = self.user.avatar return { "code": 2000, "msg": "请求成功", "data": data } class LoginView(TokenObtainPairView): """ 登录接口 """ serializer_class = LoginSerializer permission_classes = [] class LoginTokenSerializer(TokenObtainPairSerializer): """ 登录的序列化器: """ class Meta: model = Users fields = "__all__" read_only_fields = ["id"] default_error_messages = { 'no_active_account': _('账号/密码不正确') } def validate(self, attrs): if not getattr(settings, 'LOGIN_NO_CAPTCHA_AUTH', False): return { "code": 4000, "msg": "该接口暂未开通!", "data": None } data = super().validate(attrs) data['name'] = self.user.name data['userId'] = self.user.id return { "code": 2000, "msg": "请求成功", "data": data } class LoginTokenView(TokenObtainPairView): """ 登录获取token接口 """ serializer_class = LoginTokenSerializer permission_classes = [] class LogoutView(APIView): def post(self, request): return DetailResponse(msg="注销成功") class ApiLoginSerializer(CustomModelSerializer): """接口文档登录-序列化器""" username = serializers.CharField() password = serializers.CharField() class Meta: model = Users fields = ['username', 'password'] class ApiLogin(APIView): """接口文档的登录接口""" serializer_class = ApiLoginSerializer authentication_classes = [] permission_classes = [] def post(self, request): username = request.data.get('username') password = request.data.get('password') user_obj = auth.authenticate(request, username=username, password=hashlib.md5(password.encode(encoding='UTF-8')).hexdigest()) if user_obj: login(request, user_obj) return redirect('/') else: return ErrorResponse(msg="账号/密码错误")