Laravel用户权限控制:如何限制非团队成员查看对应问卷?
嘿,这个越权漏洞确实得赶紧修复,我给你几个实用的实现方案,都是Laravel项目里常用的做法,你可以根据自己的项目规模选:
修复问卷权限越权漏洞的实现方案
核心逻辑很明确:只有问卷所属团队的成员才能查看该问卷,所以我们需要先打通用户、团队、问卷三者的关联,再在访问时做权限校验。
1. 先确认数据库关联(如果还没配置的话)
假设你的数据库里有这几张表:
surveys:问卷表,需要新增team_id字段关联到teams表的主键teams:团队表user_team:用户-团队关联表(多对多),包含user_id和team_id两个字段
对应的模型关系也要配置好:
// Survey.php 模型 public function team() { return $this->belongsTo(Team::class); } // Team.php 模型 public function users() { return $this->belongsToMany(User::class); } // User.php 模型 public function teams() { return $this->belongsToMany(Team::class); }
2. 方案一:控制器内直接校验(快速修复)
适合小型项目或者临时快速修复,直接在你的viewSurvey方法里加入校验逻辑:
public function viewSurvey($id) { // 先找到目标问卷,找不到直接返回404 $survey = Survey::findOrFail($id); // 获取当前登录用户(确保路由已加auth中间件,拦截未登录访问) $currentUser = auth()->user(); // 用exists查询校验用户是否属于问卷所属团队,比加载全部用户更高效 $hasPermission = $survey->team->users()->where('user_id', $currentUser->id)->exists(); if (!$hasPermission) { // 无权限时返回403禁止访问,也可以跳转到自定义错误页面 abort(403, '你没有权限查看该问卷'); } // 权限通过,继续执行原有业务逻辑 $object = DB::table('question')->where('survey_id', '=', $id)->get(); $date = Sur... // 你的原有代码 // 返回视图或数据 return view('survey.view', compact('survey', 'object', 'date')); }
3. 方案二:使用模型策略(更优雅,适合中大型项目)
Laravel的模型策略可以把权限逻辑抽离出来,让控制器更简洁,也方便统一管理所有问卷相关的权限规则:
步骤1:生成Survey策略文件
运行Artisan命令创建策略:
php artisan make:policy SurveyPolicy
步骤2:在策略里定义view权限规则
打开app/Policies/SurveyPolicy.php,编写view方法:
public function view(User $user, Survey $survey) { // 校验用户是否在问卷所属团队中 return $survey->team->users()->where('user_id', $user->id)->exists(); }
步骤3:注册策略
打开app/Providers/AuthServiceProvider.php,在$policies数组里注册策略:
protected $policies = [ Survey::class => SurveyPolicy::class, ];
步骤4:控制器中使用策略校验
现在你的viewSurvey方法可以简化成这样:
public function viewSurvey($id) { $survey = Survey::findOrFail($id); // 自动调用SurveyPolicy的view方法校验权限,失败会自动返回403 $this->authorize('view', $survey); // 原有业务逻辑 $object = DB::table('question')->where('survey_id', '=', $id)->get(); $date = Sur... return view('survey.view', compact('survey', 'object', 'date')); }
4. 额外注意事项
- 确保访问该路由的用户必须登录:给路由加上
auth中间件,比如:Route::get('/survey/{id}', [YourController::class, 'viewSurvey'])->middleware('auth'); - 如果存在个人问卷(无所属团队),可以扩展校验逻辑,允许问卷创建者直接访问:
// 在策略或控制器里修改校验逻辑 return $survey->team->users()->where('user_id', $user->id)->exists() || $survey->creator_id == $user->id; - 避免N+1查询:可以用
with('team')预加载团队关联,减少数据库查询次数:$survey = Survey::with('team')->findOrFail($id);
内容的提问来源于stack exchange,提问作者user9278936
相关产品推荐
相关产品推荐

