You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF如何保护用户注册视图 拦截非前端来源的自动化注册请求

DRF实现仅允许前端提交注册请求的防护方案

实现思路

无法100%完全区分合法前端请求和高度伪造的请求,但可以通过多层校验组合实现极高的拦截率,同时支持开发/生产环境的逻辑切换。

方案1:自定义请求头校验(核心实现)

这是最直接的区分手段,步骤如下:

  • 第一步:React前端统一注入自定义请求头
    在前端Axios全局配置中添加专属的私有请求头,值为预设的密钥,示例配置:
    // React 端 Axios 全局配置
    import axios from 'axios'
    axios.defaults.headers.common['X-Frontend-Request-Secret'] = import.meta.env.VITE_FRONTEND_REQUEST_SECRET
    
    生产环境将密钥存在环境变量中,避免硬编码泄露。
  • 第二步:DRF端自定义校验逻辑
    编写自定义权限类,在校验逻辑中加入环境开关,开发环境直接放行,生产环境校验请求头:
    from rest_framework import permissions
    from django.conf import settings
    
    class IsFrontendRequest(permissions.BasePermission):
        def has_permission(self, request, view):
            # 开发环境直接放行,允许Postman测试
            if settings.DEBUG:
                return True
            # 生产环境校验自定义请求头
            request_secret = request.META.get('HTTP_X_FRONTEND_REQUEST_SECRET')
            return request_secret == settings.FRONTEND_REQUEST_SECRET
    
  • 第三步:将权限类绑定到注册接口
    因为你使用的是ModelViewSet,注册对应的是create动作,所以可以重写get_permissions方法,仅给注册动作加这个校验:
    class UserViewSet(viewsets.ModelViewSet):
        serializer_class = UserSerializer
        permission_classes = [NotSafeMethodAndAllowAny | permissions.IsAuthenticated]
    
        def get_permissions(self):
            perms = super().get_permissions()
            # 仅注册(create)动作添加前端请求校验
            if self.action == 'create':
                perms.append(IsFrontendRequest())
            return perms
    
        # 原有逻辑保持不变
        def get_queryset(self):
            if self.request.user.is_superuser:
                return User.objects.all()
            else:
                return User.objects.filter(id=self.request.user.id)
    
        @action(detail=False, methods=["get"])
        def current(self, request, *args, **kwargs):
            return Response(self.get_serializer(request.user).data)
    
  • 第四步:配置环境变量
    在生产环境的settings.py中添加配置:
    import os
    FRONTEND_REQUEST_SECRET = os.getenv('FRONTEND_REQUEST_SECRET', 'dev-default-secret')
    

方案2:补充CORS配置

生产环境配置django-cors-headers仅允许你的React前端域名跨域访问,虽然CORS规则对curl/Postman这类工具无效,但可以阻止其他非法网站在浏览器端调用你的注册接口:

# settings.py
CORS_ALLOWED_ORIGINS = [
    "https://你的React前端域名",
]
# 开发环境可以加入http://localhost:3000之类的本地测试地址

方案3:补充频率限制

额外配置DRF自带的限流类,给匿名用户的注册接口加频率限制,就算请求头被泄露,也能避免批量刷注册:
首先自定义限流类:

from rest_framework.throttling import AnonRateThrottle

class RegisterAnonThrottle(AnonRateThrottle):
    scope = 'register'

然后在settings.py配置限流规则:

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'register': '3/min', # 匿名用户每分钟最多3次注册请求
    }
}

最后把限流类加到UserViewSet的create动作上,同样支持环境开关:

def get_throttles(self):
    throttles = super().get_throttles()
    if self.action == 'create' and not settings.DEBUG:
        throttles.append(RegisterAnonThrottle())
    return throttles

注意事项

  • 该方案属于低成本防护,能挡住绝大多数无针对性的批量注册脚本,如果需要更高等级的防护,可以额外添加图形验证码、手机号/邮箱校验等逻辑
  • 自定义请求头的密钥要定期更换,生产环境不要硬编码在代码库中

内容的提问来源于stack exchange,提问作者dabljues

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 21:24:03