Craft多站点环境中如何实现用户仅访问对应站点资产文件夹
实现Craft多站点用户组仅访问对应站点资产文件夹的方案
下面提供三种可行的方案,覆盖代码实现到无代码配置场景,你可根据自身技术能力和需求选择:
方案一:自定义模块监听资产查询事件(代码实现)
通过监听Craft的资产查询事件,动态过滤用户可见的资产范围,仅返回对应站点文件夹下的内容。
- 在Craft项目的
modules目录下创建自定义模块(无则新建),在模块初始化方法中添加事件监听:
use craft\elements\Asset; use craft\events\DefineSourceQueryEvent; use yii\base\Event; // 监听资产源查询前的事件 Event::on(Asset::class, Asset::EVENT_BEFORE_DEFINE_SOURCE_QUERY, function(DefineSourceQueryEvent $event) { $currentUser = \Craft::$app->user->identity; if (!$currentUser) return; // 映射用户组handle到站点handle $groupSiteMap = [ 'users-site-one' => 'site-one', 'users-site-two' => 'site-two', 'users-site-three' => 'site-three', ]; // 遍历用户所属组,匹配对应站点 foreach ($currentUser->getGroups() as $group) { if (isset($groupSiteMap[$group->handle])) { $targetSiteHandle = $groupSiteMap[$group->handle]; // 过滤资产路径,只保留对应站点文件夹下的内容 $event->query->andWhere(['like', 'folderPath', "uploads/{$targetSiteHandle}/", false]); break; } } });
- 在Craft后台启用该模块,切换对应用户组账号验证效果,此时用户仅能看到
uploads/{site.handle}下的资产和文件夹。
方案二:为每个站点单独创建资产源(无代码配置)
放弃共用一个uploads资产源,改为给每个站点创建独立资产源,通过权限控制用户可见性:
- 进入Craft后台「设置」→「资产」,点击「新建资产源」:
- 第一个资产源命名为「Site One Assets」,基础路径设为
uploads/site-one,站点关联选择「site-one」; - 同理创建「Site Two Assets」和「Site Three Assets」,分别对应各自的站点路径和关联站点。
- 第一个资产源命名为「Site One Assets」,基础路径设为
- 进入「设置」→「用户组」,编辑每个用户组的权限:
- 给
users site-one组分配「Site One Assets」的查看/编辑权限,取消全局资产源的权限; - 其他用户组同理,仅分配对应站点资产源的权限。
- 给
用户登录后,资产面板只会显示自己组有权限的资产源,完全看不到其他站点的资产文件夹。
方案三:自定义权限规则控制文件夹访问(进阶配置)
通过注册自定义权限,结合事件监听控制文件夹的可见性:
- 在自定义模块中注册新权限:
use craft\services\UserPermissions; use yii\base\Event; Event::on(UserPermissions::class, UserPermissions::EVENT_REGISTER_PERMISSIONS, function($event) { $event->permissions['siteAssets'] = [ 'label' => '站点资产访问权限', 'permissions' => [ 'accessSiteOneAssets' => ['label' => '访问Site One资产'], 'accessSiteTwoAssets' => ['label' => '访问Site Two资产'], 'accessSiteThreeAssets' => ['label' => '访问Site Three资产'], ], ]; });
- 监听资产文件夹渲染事件,过滤无权限的文件夹:
use craft\events\TemplateEvent; use craft\web\View; use yii\base\Event; Event::on(View::class, View::EVENT_BEFORE_RENDER_TEMPLATE, function(TemplateEvent $event) { // 仅针对资产文件夹模板生效 if ($event->template !== '_elements/assets/_folders') return; $currentUser = \Craft::$app->user->identity; if (!$currentUser) return; // 映射权限到文件夹路径 $permissionFolderMap = [ 'accessSiteOneAssets' => 'uploads/site-one', 'accessSiteTwoAssets' => 'uploads/site-two', 'accessSiteThreeAssets' => 'uploads/site-three', ]; // 过滤文件夹数据 $folders = $event->context['folders'] ?? []; $allowedFolders = []; foreach ($folders as $folder) { foreach ($permissionFolderMap as $perm => $path) { if ($folder->path === $path && $currentUser->can($perm)) { $allowedFolders[] = $folder; break; } } } // 更新模板上下文的文件夹列表 $event->context['folders'] = $allowedFolders; });
- 给每个用户组分配对应的自定义权限,用户仅能看到自己有权限的文件夹。
注意事项
- 无论使用哪种方案,都要确保用户组未被分配全局的「管理所有资产」权限,否则会覆盖自定义权限规则。
- 测试时务必切换不同用户组账号验证,确保权限限制生效且不影响正常资产操作。
内容的提问来源于stack exchange,提问作者karlitten
相关产品推荐
相关产品推荐

