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

普通用户仅可见状态为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 08:06:02