普通用户仅可见状态为1的图片、管理员可见全部,现有实现方案是否可行?
权限逻辑实现方案评估与优化
原方案可行性说明
你的实现逻辑本身符合权限要求,但存在严重的缓存权限泄露问题:当前使用的缓存key model_show.$name 未区分管理员与普通用户身份,若管理员优先访问接口触发缓存,后续普通用户读取缓存时会直接拿到包含不可见图片的关联数据,完全违反权限规则。
更简洁的优化方案
你可以通过Laravel的条件语法简化重复分支代码,同时修复缓存问题,优化后代码如下:
public function show($name) { $isAdmin = Auth::user()->isAdmin(); // 缓存key拼接身份标识,避免不同权限用户读取到越权缓存 $cacheKey = 'model_show.' . $name . '.' . ($isAdmin ? 'admin' : 'user'); $model = cache()->remember($cacheKey, Config::get('cache.ttl'), function () use ($name, $isAdmin) { return Model::where('name', $name) ->with($isAdmin ? 'pictures' : 'visible_pictures') ->first(); }); $pictures = $model->{$isAdmin ? 'pictures' : 'visible_pictures'}() ->latest() ->paginate(18); return view('model.model', compact('model', 'pictures')); }
进一步简化(可选)
如果需要复用该权限逻辑,可以将权限判断下沉到模型层,在你的Model类中新增关联方法:
// 对应模型类中新增 public function picturesForCurrentUser() { return (auth()->check() && auth()->user()->isAdmin()) ? $this->pictures() : $this->visible_pictures(); }
控制器即可简化为无分支逻辑:
public function show($name) { $isAdmin = Auth::user()->isAdmin(); $cacheKey = 'model_show.' . $name . '.' . ($isAdmin ? 'admin' : 'user'); $model = cache()->remember($cacheKey, Config::get('cache.ttl'), function () use ($name) { return Model::where('name', $name)->first(); }); $pictures = $model->picturesForCurrentUser()->latest()->paginate(18); return view('model.model', compact('model', 'pictures')); }
这种实现后续如果要调整图片可见权限规则,只需要修改模型层的picturesForCurrentUser方法即可,不需要改动控制器代码,可维护性更强。
你认为Gates/Policy不适合该场景的判断是合理的,Gates/Policy更偏向于操作权限校验,这类数据查询层面的可见性过滤用关联方法/ Eloquent作用域实现更加直接高效。
内容的提问来源于stack exchange,提问作者Kylian
相关产品推荐
相关产品推荐

