diff --git a/backend/dvadmin/system/views/login.py b/backend/dvadmin/system/views/login.py index ea084ec..35923cc 100644 --- a/backend/dvadmin/system/views/login.py +++ b/backend/dvadmin/system/views/login.py @@ -63,32 +63,15 @@ class LoginSerializer(TokenObtainPairSerializer): fields = "__all__" read_only_fields = ["id"] -class LoginView(TokenObtainPairView): - """ - 登录接口 - """ - serializer_class = LoginSerializer - permission_classes = [] + default_error_messages = {"no_active_account": _("账号/密码错误")} - def post(self, request, *args, **kwargs): - # username可能携带的不止是用户名,可能还是用户的其它唯一标识 手机号 邮箱 - username = request.data.get('username',None) - if username is None: - return ErrorResponse(msg="参数错误") - password = request.data.get('password',None) - if password is None: - return ErrorResponse(msg="参数错误") - captcha = request.data.get('captcha',None) - if captcha is None: - return ErrorResponse(msg="参数错误") - captchaKey = request.data.get('captchaKey',None) - if captchaKey is None: - return ErrorResponse(msg="参数错误") + def validate(self, attrs): + captcha = self.initial_data.get("captcha", None) if dispatch.get_system_config_values("base.captcha_state"): if captcha is None: raise CustomValidationError("验证码不能为空") self.image_code = CaptchaStore.objects.filter( - id=captchaKey + 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: @@ -103,36 +86,98 @@ class LoginView(TokenObtainPairView): else: self.image_code and self.image_code.delete() raise CustomValidationError("图片验证码错误") - try: - # 手动通过 user 签发 jwt-token - user = Users.objects.get(username=username) - except: - return DetailResponse(msg='该账号未注册') - # 获得用户后,校验密码并签发token - if check_password(make_password(password),user.password): - return DetailResponse(msg='密码错误') - result = { - "name":user.name, - "userId":user.id, - "avatar":user.avatar, - } - dept = getattr(user, 'dept', None) + data = super().validate(attrs) + data["name"] = self.user.name + data["userId"] = self.user.id + data["avatar"] = self.user.avatar + data['user_type'] = self.user.user_type + dept = getattr(self.user, 'dept', None) if dept: - result['dept_info'] = { + data['dept_info'] = { 'dept_id': dept.id, 'dept_name': dept.name, - 'dept_key': dept.key + } - role = getattr(user, 'role', None) + role = getattr(self.user, 'role', None) if role: - result['role_info'] = role.values('id', 'name', 'key') - refresh = LoginSerializer.get_token(user) - result["refresh"] = str(refresh) - result["access"] = str(refresh.access_token) + data['role_info'] = role.values('id', 'name', 'key') + request = self.context.get("request") + request.user = self.user # 记录登录日志 - request.user = user save_login_log(request=request) - return DetailResponse(data=result,msg="获取成功") + return {"code": 2000, "msg": "请求成功", "data": data} + +class LoginView(TokenObtainPairView): + """ + 登录接口 + """ + serializer_class = LoginSerializer + permission_classes = [] + + # def post(self, request, *args, **kwargs): + # # username可能携带的不止是用户名,可能还是用户的其它唯一标识 手机号 邮箱 + # username = request.data.get('username',None) + # if username is None: + # return ErrorResponse(msg="参数错误") + # password = request.data.get('password',None) + # if password is None: + # return ErrorResponse(msg="参数错误") + # captcha = request.data.get('captcha',None) + # if captcha is None: + # return ErrorResponse(msg="参数错误") + # captchaKey = request.data.get('captchaKey',None) + # if captchaKey is None: + # return ErrorResponse(msg="参数错误") + # if dispatch.get_system_config_values("base.captcha_state"): + # if captcha is None: + # raise CustomValidationError("验证码不能为空") + # self.image_code = CaptchaStore.objects.filter( + # id=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("图片验证码错误") + # try: + # # 手动通过 user 签发 jwt-token + # user = Users.objects.get(username=username) + # except: + # return DetailResponse(msg='该账号未注册') + # # 获得用户后,校验密码并签发token + # print(make_password(password),user.password) + # if check_password(make_password(password),user.password): + # return DetailResponse(msg='密码错误') + # result = { + # "name":user.name, + # "userId":user.id, + # "avatar":user.avatar, + # } + # dept = getattr(user, 'dept', None) + # if dept: + # result['dept_info'] = { + # 'dept_id': dept.id, + # 'dept_name': dept.name, + # 'dept_key': dept.key + # } + # role = getattr(user, 'role', None) + # if role: + # result['role_info'] = role.values('id', 'name', 'key') + # refresh = LoginSerializer.get_token(user) + # result["refresh"] = str(refresh) + # result["access"] = str(refresh.access_token) + # # 记录登录日志 + # request.user = user + # save_login_log(request=request) + # return DetailResponse(data=result,msg="获取成功") class LoginTokenSerializer(TokenObtainPairSerializer): diff --git a/backend/dvadmin/utils/exception.py b/backend/dvadmin/utils/exception.py index 394814f..8498441 100644 --- a/backend/dvadmin/utils/exception.py +++ b/backend/dvadmin/utils/exception.py @@ -11,14 +11,19 @@ import traceback from django.db.models import ProtectedError from django.http import Http404 -from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed -from rest_framework.views import set_rollback +from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed, NotAuthenticated +from rest_framework.status import HTTP_401_UNAUTHORIZED +from rest_framework.views import set_rollback, exception_handler from dvadmin.utils.json_response import ErrorResponse logger = logging.getLogger(__name__) +class CustomAuthenticationFailed(NotAuthenticated): + # 设置 status_code 属性为 400 + status_code = 400 + def CustomExceptionHandler(ex, context): """ 统一异常拦截处理 @@ -30,9 +35,14 @@ def CustomExceptionHandler(ex, context): """ msg = '' code = 4000 - + # 调用默认的异常处理函数 + response = exception_handler(ex, context) if isinstance(ex, AuthenticationFailed): code = 401 + code_type = response.data.get('detail').code + if code_type == 'no_active_account': + code=400 + return ErrorResponse(status=HTTP_401_UNAUTHORIZED) msg = ex.detail elif isinstance(ex,Http404): code = 400 diff --git a/web/src/stores/dictionary.ts b/web/src/stores/dictionary.ts index 656b9ca..0a5eab2 100644 --- a/web/src/stores/dictionary.ts +++ b/web/src/stores/dictionary.ts @@ -53,7 +53,6 @@ export const DictionaryStore = defineStore('Dictionary', { break } }) - console.log(childrens) this.data[item.value]=childrens }); }); diff --git a/web/src/utils/service.ts b/web/src/utils/service.ts index 50bce47..8798898 100644 --- a/web/src/utils/service.ts +++ b/web/src/utils/service.ts @@ -1,5 +1,8 @@ import axios from 'axios'; import { get } from 'lodash-es'; +import { ElMessage, ElMessageBox } from 'element-plus' +import type { Action } from 'element-plus' + // @ts-ignore import { errorLog, errorCreate } from './tools.ts'; // import { env } from "/src/utils/util.env"; @@ -58,11 +61,22 @@ function createService() { } else { // 有 code 代表这是一个后端接口 可以进行进一步的判断 switch (code) { + case 400: + Local.clear(); + Session.clear(); + errorCreate(`${dataAxios.msg}: ${response.config.url}`); + window.location.reload(); + break; case 401: Local.clear(); Session.clear(); - window.location.reload(); dataAxios.msg = '登录授权过期,请重新登录'; + ElMessageBox.alert(dataAxios.msg, '提示', { + confirmButtonText: 'OK', + callback: (action: Action) => { + window.location.reload(); + }, + }) errorCreate(`${dataAxios.msg}: ${response.config.url}`); break; case 2000: