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

Django登录用户资料访问权限控制问题求助

解决Django用户资料编辑的权限漏洞:限制用户仅能编辑自身资料

问题根源

你的代码目前存在两个核心问题:

  1. 未校验当前登录用户与URL中user_id对应的用户是否一致,导致任意登录用户修改user_id即可访问他人资料
  2. 原视图通过@user_passes_test(check_role_super)限制仅超级管理员能访问,不符合普通用户编辑自身资料的需求

解决方案

根据需求,我们可以分两种场景处理:普通用户仅能编辑自身资料,超级管理员可编辑所有用户资料,同时对越权访问触发错误提示。

方案1:拆分视图(推荐,职责更清晰)

1. 普通用户资料编辑视图(无需URL参数)

直接使用当前登录用户,从根源避免用户通过修改URL参数越权:

@login_required(login_url='signin')
def profile_edit(request):
    # 直接获取当前登录用户
    user = request.user
    # 通过OneToOne关联获取用户资料,比直接用pk更可靠
    user_profile = get_object_or_404(userMember, user=user)

    if request.method == 'POST':
        # 使用普通用户专属表单(仅开放可修改的个人字段,如姓名、联系方式等)
        form = UserForm(request.POST, instance=user)
        # 处理图片上传需传入request.FILES
        form_profile = MemberForm(request.POST, request.FILES, instance=user_profile)
        
        if form.is_valid() and form_profile.is_valid():
            form.save()
            form_profile.save()
            # 保存后跳转回个人资料页
            return redirect('profile')
    else:
        form = UserForm(instance=user)
        form_profile = MemberForm(instance=user_profile)

    context = {
        'form': form,
        'user': user,
        'form_profile': form_profile,
        'user_profile': user_profile
    }
    return render(request, 'pages/profile_edit.html', context)
2. 超级管理员资料编辑视图(保留原逻辑并优化)

保留超级管理员的全局编辑权限,同时优化关联资料的获取方式:

@login_required(login_url='signin')
@user_passes_test(check_role_super)
def sa_profile_edit(request, user_id=None):
    user = get_object_or_404(User, pk=user_id)
    # 通过User实例关联获取userMember,避免主键不一致问题
    user_profile = get_object_or_404(userMember, user=user)
    
    if request.method == 'POST':
        form = UserFormAdmin(request.POST, instance=user)
        form_profile = MemberForm(request.POST, request.FILES, instance=user_profile)
        
        if form.is_valid() and form_profile.is_valid():
            form.save()
            form_profile.save()
            return redirect('sa_user_list')  # 跳转回用户管理列表
    else:
        form = UserFormAdmin(instance=user)
        form_profile = MemberForm(instance=user_profile)       
    
    context = {
        'form': form,
        'user': user,
        'form_profile': form_profile,
        'user_profile': user_profile
    }
    return render(request, 'pages/sa_editProfile.html', context)

方案2:合并视图(支持两种角色共用一个接口)

如果需要用同一个视图处理两种角色,可在视图内添加权限判断逻辑:

@login_required(login_url='signin')
def profile_edit(request, user_id=None):
    # 默认使用当前登录用户ID,未传参时直接编辑自身资料
    target_user_id = user_id or request.user.id
    user = get_object_or_404(User, pk=target_user_id)
    user_profile = get_object_or_404(userMember, user=user)

    # 权限校验:超级管理员可编辑任意用户,其他用户仅能编辑自己
    if request.user.role != User.SUPERADMIN and user.id != request.user.id:
        raise PermissionDenied("你仅能编辑自己的资料")

    if request.method == 'POST':
        # 根据角色选择对应的表单,普通用户无法修改敏感字段
        form_class = UserFormAdmin if request.user.role == User.SUPERADMIN else UserForm
        form = form_class(request.POST, instance=user)
        form_profile = MemberForm(request.POST, request.FILES, instance=user_profile)
        
        if form.is_valid() and form_profile.is_valid():
            form.save()
            form_profile.save()
            return redirect('profile', user_id=request.user.id)
    else:
        form_class = UserFormAdmin if request.user.role == User.SUPERADMIN else UserForm
        form = form_class(instance=user)
        form_profile = MemberForm(instance=user_profile)

    context = {
        'form': form,
        'user': user,
        'form_profile': form_profile,
        'user_profile': user_profile
    }
    return render(request, 'pages/profile_edit.html', context)

错误提示处理

为了给用户明确的越权提示,需要配置自定义403错误页面:

  1. 在项目urls.py中添加:
handler403 = 'your_app.views.permission_denied'
  1. 在views.py中编写错误处理视图:
def permission_denied(request, exception):
    return render(request, '403.html', {'message': str(exception)}, status=403)
  1. 创建403.html模板显示错误信息:
<!DOCTYPE html>
<html>
<head>
    <title>权限不足</title>
</head>
<body>
    <h1>权限不足</h1>
    <p>{{ message }}</p>
    <a href="{% url 'profile' %}">返回个人资料页</a>
</body>
</html>

额外优化建议

  • 普通用户的表单(UserForm)应限制可编辑字段,隐藏role、status等敏感字段,避免用户通过表单篡改权限
  • 确保userMember模型的user关联正确使用OneToOneField,避免数据不一致问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:10:38