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

Django如何禁止用户直接访问otp/端点 仅允许注册流程跳转访问

Django限制otp/端点仅允许注册流程访问的实现方案

核心逻辑

你现有代码已经在session中存储了注册过程的OTP、用户手机号、密码等临时信息,直接用服务端session存储访问权限标记即可实现拦截,不要用可被客户端篡改的Referer请求头做校验,这套方案改造成本极低,完全适配现有代码逻辑。

具体修改步骤

  • 第一步:调整注册视图跳转逻辑
    在注册视图中,完成注册表单校验、生成OTP、将otp/姓名/手机号/密码等临时信息存入session之后,跳转至otp页面前,新增一行代码写入访问许可标记:

    # 标记当前请求已走完注册前置流程,允许访问OTP页
    request.session['can_access_otp'] = True
    # 保留原有跳转OTP的逻辑即可
    return redirect('otp')
    
  • 第二步:改造OTPView增加统一入口校验
    你原有代码的GET方法没有任何访问校验,是用户直接输入URL就能进入页面的核心原因。借助Django视图自带的dispatch方法做全局校验,不用在GET、POST里重复写判断逻辑,修改后的完整视图代码如下:

    class OTPView(View):
        def dispatch(self, request, *args, **kwargs):
            # 所有请求进入视图前先校验访问资格
            required_session_keys = ['can_access_otp', 'otp', 'first_name', 'last_name', 'password', 'phone']
            # 必须同时满足:有访问许可 + 所有注册流程必填的session字段存在
            if not all(request.session.get(key) for key in required_session_keys):
                # 校验不通过时清理残留的脏session数据
                for key in required_session_keys:
                    if key in request.session:
                        del request.session[key]
                messages.error(request, '请先完成注册信息填写')
                return redirect('signup')
            return super().dispatch(request, *args, **kwargs)
    
        def get(self, request, *args, **kwargs):
            otp_form = OTP_Form()
            return render(request, 'otp.html', {'otp_form': otp_form})
    
        def post(self, request, *args, **kwargs):
            try:
                otp = request.session.get('otp')
                first_name = request.session.get('first_name')
                last_name = request.session.get('last_name')
                password = request.session.get('password')
                phone = request.session.get('phone')
                otp_form = OTP_Form(request.POST)
                if otp_form.is_valid():
                    get_otp = otp_form.cleaned_data['otp']
                    if get_otp == otp:
                        user = MyUser.objects.create_user(
                            phone=phone, password=password, first_name=first_name, last_name=last_name)
                        user.save()
                        otp_entry = OTP.objects.create(user_id=user, otp=otp)
                        otp_entry.save()
                        delete_session(request)
                        # 验证通过后额外删除访问许可,避免后续重复进入页面
                        if 'can_access_otp' in request.session:
                            del request.session['can_access_otp']
                        messages.success(
                            request, 'Your account has been created')
                        return redirect('login')
                    else:
                        messages.error(request, 'Incorrect OTP')
                        return redirect('otp')
                else:
                    messages.error(request, 'Please enter the OTP again')
                    return redirect('otp')
            except:
                # 流程异常时同步清理访问许可
                if 'can_access_otp' in request.session:
                    del request.session['can_access_otp']
                messages.error(request, 'Please try signing up again')
                return redirect('signup')
    

边界场景适配说明

  • 用户直接在浏览器输入/otp/地址访问:未经过注册流程写入许可标记,会被直接拦截跳回注册页
  • OTP输入错误重定向回OTP页:session内的许可标记和注册临时信息均保留,可正常访问,不影响业务流程
  • 用户注册中途关闭页面后重新输入OTP地址:只要session内必填字段缺失,就会被拦截,不会加载空白的OTP校验页
  • OTP验证成功跳转登录页后:许可标记已被删除,再次输入OTP地址也无法访问
  • 原有路由配置path('otp/', OTPView.as_view(), name='otp')无需任何修改,保持原样即可。

内容的提问来源于stack exchange,提问作者Noor ul ain Ibrahim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:57:20