76 lines
2.9 KiB
Python
76 lines
2.9 KiB
Python
|
|
import base64
|
||
|
|
import os
|
||
|
|
|
||
|
|
from django.conf import settings
|
||
|
|
from django.contrib.auth import authenticate
|
||
|
|
from django.db.utils import OperationalError, ProgrammingError
|
||
|
|
from gmssl import sm4
|
||
|
|
from rest_framework.response import Response
|
||
|
|
from rest_framework.views import APIView
|
||
|
|
from rest_framework_simplejwt.tokens import RefreshToken
|
||
|
|
|
||
|
|
|
||
|
|
class UserLoginView(APIView):
|
||
|
|
def post(self, request, *args, **kwargs):
|
||
|
|
if os.environ.get("DJANGO_LOGIN_BREAKPOINT", "").strip().lower() in {
|
||
|
|
"1",
|
||
|
|
"true",
|
||
|
|
"yes",
|
||
|
|
"y",
|
||
|
|
"on",
|
||
|
|
}:
|
||
|
|
breakpoint()
|
||
|
|
try:
|
||
|
|
username = request.data.get("username")
|
||
|
|
encrypted_password = request.data.get("password")
|
||
|
|
if not username or not encrypted_password:
|
||
|
|
return Response({"code": "1", "error": "用户名或密码不能为空"})
|
||
|
|
|
||
|
|
private_key = getattr(settings, "SM4_PRIVATE_KEY", getattr(settings, "private_key", ""))
|
||
|
|
if not private_key:
|
||
|
|
return Response({"code": "1", "error": "缺少加密密钥"})
|
||
|
|
|
||
|
|
try:
|
||
|
|
password = self.decrypt_password(encrypted_password, private_key)
|
||
|
|
except Exception:
|
||
|
|
return Response({"code": "1", "error": "密码解密失败"})
|
||
|
|
|
||
|
|
user = authenticate(request, username=username, password=password)
|
||
|
|
|
||
|
|
if user is not None:
|
||
|
|
refresh = RefreshToken.for_user(user)
|
||
|
|
user_groups = [group.id for group in user.groups.all()]
|
||
|
|
return Response(
|
||
|
|
{
|
||
|
|
"access_token": str(refresh.access_token),
|
||
|
|
"refresh_token": str(refresh),
|
||
|
|
"user_id": user.id,
|
||
|
|
"username": user.username,
|
||
|
|
"email": user.email,
|
||
|
|
"groups": user_groups,
|
||
|
|
"is_superuser": user.is_superuser,
|
||
|
|
}
|
||
|
|
)
|
||
|
|
|
||
|
|
return Response({"code": "1", "error": "用户名或密码不正确,请检查并重试!"})
|
||
|
|
except (OperationalError, ProgrammingError) as e:
|
||
|
|
payload = {"code": "1", "error": "数据库未就绪,请先执行 migrate 并检查 DB 配置"}
|
||
|
|
if settings.DEBUG:
|
||
|
|
payload["details"] = str(e)
|
||
|
|
return Response(payload)
|
||
|
|
except Exception as e:
|
||
|
|
payload = {"code": "1", "error": "登录服务异常"}
|
||
|
|
if settings.DEBUG:
|
||
|
|
payload["details"] = str(e)
|
||
|
|
return Response(payload)
|
||
|
|
|
||
|
|
def decrypt_password(self, encrypted_text, private_key):
|
||
|
|
if not private_key or len(private_key) != 16:
|
||
|
|
raise ValueError("invalid sm4 key")
|
||
|
|
cipher = sm4.CryptSM4()
|
||
|
|
cipher.set_key(private_key.encode(), True)
|
||
|
|
|
||
|
|
encrypted_bytes = base64.b64decode(encrypted_text)
|
||
|
|
decrypted_bytes = cipher.crypt_ecb(encrypted_bytes)
|
||
|
|
return decrypted_bytes.decode()
|