107 lines
3.9 KiB
Python
107 lines
3.9 KiB
Python
from rest_framework.permissions import AllowAny
|
|
from rest_framework.views import APIView
|
|
from rest_framework import status
|
|
from drf_yasg.utils import swagger_auto_schema
|
|
from drf_yasg import openapi
|
|
from chunyu_project.common_schemas import success_response, error_response, unauthorized_response, not_found_response
|
|
|
|
from utils.slider_captcha import (
|
|
generate_slider_captcha,
|
|
verify_slider_captcha,
|
|
verify_slider_trajectory,
|
|
SliderCaptchaError
|
|
)
|
|
from utils.response_codes import (
|
|
ResponseCode,
|
|
create_standardized_response,
|
|
create_standardized_error_response,
|
|
)
|
|
|
|
|
|
class SliderCaptchaGenerateView(APIView):
|
|
permission_classes = [AllowAny]
|
|
|
|
@swagger_auto_schema(
|
|
tags=['验证码'],
|
|
operation_summary='生成滑块验证码',
|
|
operation_description='生成新的滑块验证码,返回背景图、滑块图和验证 key',
|
|
responses={200: success_response, 500: error_response},
|
|
)
|
|
def get(self, request):
|
|
try:
|
|
captcha_data = generate_slider_captcha()
|
|
return create_standardized_response(
|
|
data=captcha_data,
|
|
code=ResponseCode.SUCCESS,
|
|
status_code=status.HTTP_200_OK
|
|
)
|
|
except Exception as e:
|
|
return create_standardized_error_response(
|
|
message=str(e),
|
|
code=ResponseCode.SERVER_INTERNAL_ERROR,
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
)
|
|
|
|
|
|
class SliderCaptchaVerifyView(APIView):
|
|
permission_classes = [AllowAny]
|
|
|
|
@swagger_auto_schema(
|
|
tags=['验证码'],
|
|
operation_summary='验证滑块验证码',
|
|
operation_description='验证滑块验证码结果,支持滑动轨迹可选',
|
|
request_body=openapi.Schema(
|
|
type=openapi.TYPE_OBJECT,
|
|
properties={
|
|
'captcha_key': openapi.Schema(type=openapi.TYPE_STRING, description='验证码 key'),
|
|
'x_position': openapi.Schema(type=openapi.TYPE_INTEGER, description='滑块 X 坐标'),
|
|
'trajectory': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_NUMBER), description='滑动轨迹数组'),
|
|
},
|
|
),
|
|
responses={200: success_response, 400: error_response, 500: error_response},
|
|
)
|
|
def post(self, request):
|
|
captcha_key = request.data.get('captcha_key')
|
|
x_position = request.data.get('x_position')
|
|
trajectory = request.data.get('trajectory')
|
|
|
|
if not captcha_key or x_position is None:
|
|
return create_standardized_error_response(
|
|
message='缺少必要参数',
|
|
code=ResponseCode.PARAMETER_ERROR,
|
|
status_code=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
|
|
try:
|
|
x_position = int(x_position)
|
|
except (ValueError, TypeError):
|
|
return create_standardized_error_response(
|
|
message='位置参数无效',
|
|
code=ResponseCode.PARAMETER_ERROR,
|
|
status_code=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
|
|
try:
|
|
if trajectory:
|
|
verified = verify_slider_trajectory(captcha_key, x_position, trajectory)
|
|
else:
|
|
verified = verify_slider_captcha(captcha_key, x_position)
|
|
|
|
return create_standardized_response(
|
|
data={'verified': verified},
|
|
code=ResponseCode.SUCCESS,
|
|
status_code=status.HTTP_200_OK
|
|
)
|
|
except SliderCaptchaError as e:
|
|
return create_standardized_error_response(
|
|
message=str(e),
|
|
code=ResponseCode.CAPTCHA_EXPIRED,
|
|
status_code=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
except Exception as e:
|
|
return create_standardized_error_response(
|
|
message=str(e),
|
|
code=ResponseCode.SERVER_INTERNAL_ERROR,
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
)
|