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
相关产品推荐
相关产品推荐

