mirror of
https://github.com/yyhuni/xingrin.git
synced 2026-01-31 11:46:16 +08:00
174 lines
5.5 KiB
Python
174 lines
5.5 KiB
Python
"""
|
||
认证相关视图
|
||
使用 Django 内置认证系统,支持 Session 认证
|
||
"""
|
||
import logging
|
||
from django.contrib.auth import authenticate, login, logout, update_session_auth_hash
|
||
from django.views.decorators.csrf import csrf_exempt
|
||
from django.utils.decorators import method_decorator
|
||
from rest_framework import status
|
||
from rest_framework.views import APIView
|
||
from rest_framework.response import Response
|
||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
@method_decorator(csrf_exempt, name='dispatch')
|
||
class LoginView(APIView):
|
||
"""
|
||
用户登录
|
||
POST /api/auth/login/
|
||
"""
|
||
authentication_classes = [] # 禁用认证(绕过 CSRF)
|
||
permission_classes = [AllowAny]
|
||
|
||
def post(self, request):
|
||
username = request.data.get('username')
|
||
password = request.data.get('password')
|
||
|
||
if not username or not password:
|
||
return Response(
|
||
{'error': '请提供用户名和密码'},
|
||
status=status.HTTP_400_BAD_REQUEST
|
||
)
|
||
|
||
user = authenticate(request, username=username, password=password)
|
||
|
||
if user is not None:
|
||
login(request, user)
|
||
logger.info(f"用户 {username} 登录成功")
|
||
return Response({
|
||
'message': '登录成功',
|
||
'user': {
|
||
'id': user.id,
|
||
'username': user.username,
|
||
'isStaff': user.is_staff,
|
||
'isSuperuser': user.is_superuser,
|
||
}
|
||
})
|
||
else:
|
||
logger.warning(f"用户 {username} 登录失败:用户名或密码错误")
|
||
return Response(
|
||
{'error': '用户名或密码错误'},
|
||
status=status.HTTP_401_UNAUTHORIZED
|
||
)
|
||
|
||
|
||
@method_decorator(csrf_exempt, name='dispatch')
|
||
class LogoutView(APIView):
|
||
"""
|
||
用户登出
|
||
POST /api/auth/logout/
|
||
"""
|
||
authentication_classes = [] # 禁用认证(绕过 CSRF)
|
||
permission_classes = [AllowAny]
|
||
|
||
def post(self, request):
|
||
# 从 session 获取用户名用于日志
|
||
user_id = request.session.get('_auth_user_id')
|
||
if user_id:
|
||
from django.contrib.auth import get_user_model
|
||
User = get_user_model()
|
||
try:
|
||
user = User.objects.get(pk=user_id)
|
||
username = user.username
|
||
logout(request)
|
||
logger.info(f"用户 {username} 已登出")
|
||
except User.DoesNotExist:
|
||
logout(request)
|
||
else:
|
||
logout(request)
|
||
return Response({'message': '已登出'})
|
||
|
||
|
||
@method_decorator(csrf_exempt, name='dispatch')
|
||
class MeView(APIView):
|
||
"""
|
||
获取当前用户信息
|
||
GET /api/auth/me/
|
||
"""
|
||
authentication_classes = [] # 禁用认证(绕过 CSRF)
|
||
permission_classes = [AllowAny]
|
||
|
||
def get(self, request):
|
||
# 从 session 获取用户
|
||
from django.contrib.auth import get_user_model
|
||
User = get_user_model()
|
||
|
||
user_id = request.session.get('_auth_user_id')
|
||
if user_id:
|
||
try:
|
||
user = User.objects.get(pk=user_id)
|
||
return Response({
|
||
'authenticated': True,
|
||
'user': {
|
||
'id': user.id,
|
||
'username': user.username,
|
||
'isStaff': user.is_staff,
|
||
'isSuperuser': user.is_superuser,
|
||
}
|
||
})
|
||
except User.DoesNotExist:
|
||
pass
|
||
|
||
return Response({
|
||
'authenticated': False,
|
||
'user': None
|
||
})
|
||
|
||
|
||
@method_decorator(csrf_exempt, name='dispatch')
|
||
class ChangePasswordView(APIView):
|
||
"""
|
||
修改密码
|
||
POST /api/auth/change-password/
|
||
"""
|
||
authentication_classes = [] # 禁用认证(绕过 CSRF)
|
||
permission_classes = [AllowAny] # 手动检查登录状态
|
||
|
||
def post(self, request):
|
||
# 手动检查登录状态(从 session 获取用户)
|
||
from django.contrib.auth import get_user_model
|
||
User = get_user_model()
|
||
|
||
user_id = request.session.get('_auth_user_id')
|
||
if not user_id:
|
||
return Response(
|
||
{'error': '请先登录'},
|
||
status=status.HTTP_401_UNAUTHORIZED
|
||
)
|
||
|
||
try:
|
||
user = User.objects.get(pk=user_id)
|
||
except User.DoesNotExist:
|
||
return Response(
|
||
{'error': '用户不存在'},
|
||
status=status.HTTP_401_UNAUTHORIZED
|
||
)
|
||
|
||
# CamelCaseParser 将 oldPassword -> old_password
|
||
old_password = request.data.get('old_password')
|
||
new_password = request.data.get('new_password')
|
||
|
||
if not old_password or not new_password:
|
||
return Response(
|
||
{'error': '请提供旧密码和新密码'},
|
||
status=status.HTTP_400_BAD_REQUEST
|
||
)
|
||
|
||
if not user.check_password(old_password):
|
||
return Response(
|
||
{'error': '旧密码错误'},
|
||
status=status.HTTP_400_BAD_REQUEST
|
||
)
|
||
|
||
user.set_password(new_password)
|
||
user.save()
|
||
|
||
# 更新 session,避免用户被登出
|
||
update_session_auth_hash(request, user)
|
||
|
||
logger.info(f"用户 {user.username} 已修改密码")
|
||
return Response({'message': '密码修改成功'})
|