如何在Django中防止登录用户查看他人订单并返回403状态?
解决Django订单详情页的权限控制问题
问题分析
你当前的代码在get_context_data里的权限检查逻辑有误(错误地拿selectedproduct_set的第一个对象和用户对比,应该直接校验订单的user字段),且返回空上下文的方式不符合HTTP规范,正确做法是直接返回403禁止访问响应。
方法一:使用UserPassesTestMixin(推荐)
UserPassesTestMixin可与LoginRequiredMixin配合,在验证用户登录后,额外校验用户是否有权访问当前订单:
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.views.generic.detail import DetailView class OrderDetailView(LoginRequiredMixin, UserPassesTestMixin, DetailView): model = Order def test_func(self): # 获取当前订单对象并校验所有者 order = self.get_object() return order.user == self.request.user def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["object_list"] = self.object.selectedproduct_set.all() context["grand_total"] = get_total(context["object_list"]) return context
当test_func返回False时,Django会自动返回403状态码,无需手动处理。
方法二:重写get_object方法
在获取订单对象的阶段就做权限校验,不符合条件直接抛出PermissionDenied异常:
from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic.detail import DetailView from django.core.exceptions import PermissionDenied class OrderDetailView(LoginRequiredMixin, DetailView): model = Order def get_object(self, queryset=None): obj = super().get_object(queryset=queryset) # 校验当前用户是否为订单所有者 if obj.user != self.request.user: raise PermissionDenied() return obj def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["object_list"] = self.object.selectedproduct_set.all() context["grand_total"] = get_total(context["object_list"]) return context
抛出PermissionDenied后,Django会自动返回403响应,完全符合HTTP权限控制规范。
注意事项
- 移除原
get_context_data中错误的权限检查代码,避免逻辑冲突。 - 确保
Order模型的user字段正确关联登录用户,保证权限校验的准确性。
内容的提问来源于stack exchange,提问作者Kifsif
相关产品推荐
相关产品推荐

