Django权限校验装饰器如何重定向回原页?无权限访问最优处理方案是什么?
无权限访问处理实现与方案选型
一、重定向回来源页面的实现方法
你当前使用的Django内置user_passes_test默认已经支持来源地址传递,根据你的实际需求可以选择两种实现逻辑:
1. 登录后跳转回用户原访问页面(常用逻辑)
user_passes_test会自动将用户尝试访问的受限页面地址作为next参数(参数名由redirect_field_name指定,默认值为next)附加到登录页URL后。
只需要在登录模板的表单中添加隐藏字段即可实现登录后自动跳转回原页面:
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}">
2. 权限校验失败直接跳转回用户上一个浏览页面
如果需要用户触发权限不足时直接返回上一页,不需要经过登录流程,可改写装饰器读取请求头HTTP_REFERER实现:
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth import REDIRECT_FIELD_NAME from django.shortcuts import redirect from functools import wraps def is_student(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None, redirect_to_referer=False): def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): # 权限校验通过直接返回视图 if request.user.is_authenticated and request.user.role == 'role1': return view_func(request, *args, **kwargs) # 开启直接跳转来源页开关则走该逻辑 if redirect_to_referer: # 取不到来源页时默认跳转首页 referer = request.META.get('HTTP_REFERER', '/') return redirect(referer) # 否则走默认跳转登录页逻辑 return user_passes_test( lambda u: False, login_url=login_url, redirect_field_name=redirect_field_name )(view_func)(request, *args, **kwargs) return _wrapped_view if function: return decorator(function) return decorator
使用时给装饰器传参redirect_to_referer=True即可生效。
二、三类处理方案的最优选择
三类方案没有绝对的最优解,需要根据用户身份场景选择:
- 未登录用户访问受限页面:优先选择第三种跳转登录页的方案,配合
next参数实现登录后回跳原页面,符合用户操作预期,不会打断正常访问流程。 - 已登录但无权限的用户访问受限页面:优先选择第二种返回权限不足错误页(HTTP 403状态码)的方案,跳回上一页会导致用户没有明确的错误反馈,容易重复触发操作;跳转登录页会误导用户认为登录失效,反复登录也无法解决问题,两种体验都极差。
- 只有在极特殊的临时场景下(比如用户访问了已过期的活动页),才适合选择第一种直接重定向回来源页的方案。
行业通用的最佳实践是分场景组合使用二、三方案,基本不需要用到直接重定向回来源页的逻辑。
内容的提问来源于stack exchange,提问作者sixovov947
相关产品推荐
相关产品推荐

