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

多用户组角色合并异常:单用户多组权限未整合的技术修复请求

合并用户所有组角色权限的问题与修复

需求

实现合并用户所属全部用户组角色的功能,确保单个用户能获取所有组的权限。

现有PHP代码

GetRoles方法

public function GetRoles($id = 'new', $module = null) {
    $json = [];

    $groups = array_merge((array) ($this->auth['payload']['group'] ?? null), (array) ($this->auth['payload']['additionalGroup'] ?? null));
    $access = GetAccess($module ?? $this->module, $groups);

    $json['insert']   = ($id === 'new' && in_array('insert', $access)) ? true : null;
    $json['view']     = ($id === 'view' && in_array('view', $access)) ? true : null;
    $json['update']   = ($id !== 'new' && in_array('update', $access)) ? true : null;
    $json['delete']   = ($id !== 'new' && in_array('delete', $access)) ? true : null;
    $json['upload']   = ($id !== 'new' && in_array('upload', $access)) ? true : null;
    $json['remove']   = ($id !== 'new' && in_array('remove', $access)) ? true : null;
    $json['inactive'] = ($id !== 'new' && in_array('inactive', $access)) ? true : null;
    $json['approve']  = ($id !== 'new' && in_array('approve', $access)) ? true : null;
    $json['cancel']   = ($id !== 'new' && in_array('cancel', $access)) ? true : null;
    $json['reopen']   = ($id !== 'new' && in_array('reopen', $access)) ? true : null;

    return $json;
}

GetAccess函数

function GetAccess($module, $groups, $role = null) {
    global $config;

    $rules   = [];
    $modules = ModuleMerge($config['modules']);

    if (isset($config['access'][$module])) {
        foreach ($config['access'][$module] ?? [] as $key => $value) {
            if (in_array($key, $groups)) {
                $rules = array_unique(array_merge($rules, $value));
            }
        }
    } else if (in_array($module, ['main', 'login', 'login_google', 'register', 'reset', 'newpassword', 'validate', 'contact_us', 'disclaimer', 'privacy_policy', 'security_policy', 'terms_condition', 'help'])) {
        $rules = ['view', 'insert', 'update'];
    } else {
        $rules = $modules[$module];
    }

    if ($role) {
        $rules = in_array($role, $rules);
    }

    return $rules;
}

ModuleMerge函数

function ModuleMerge($array) {
    $result = [];

    for ($i = 0; $i < count($array); $i++) {
        $moduleKey = $array[$i]['module'] ?? null;

        if (!isset($result[$moduleKey])) {
            $result[$moduleKey] = [];
        }

        $result[$moduleKey] = $result[$moduleKey]
        ? array_unique(array_merge($result[$moduleKey], $array[$i]['roles'] ?? []))
        : ($array[$i]['roles'] ?? []);

        if (is_array($array[$i]['children'] ?? null)) {
            $result = array_merge($result, ModuleMerge($array[$i]['children']));
        }
    }

    return $result;
}

场景与问题

场景

用户1所属主组为['Staff'],附加组为['Store Admin', 'Merchandise', 'Inventory SV'];各角色组权限分别为:

  • Staff组:['View main dashboard', 'edit profile', 'upload profile picture']
  • Store Admin组:['View store module page', 'add store item', 'update store item', 'delete store item', 'approve store item']
  • Merchandise组:['View merchandise stock', 'insert merchandise recipient']

问题

当前用户1仅能访问主组角色权限,附加组角色未被合并,实际结果为['View main dashboard', 'edit profile', 'upload profile picture'],期望结果为整合所有组的角色权限:['View main dashboard', 'edit profile', 'upload profile picture', 'View store module page', 'add store item', 'update store item', 'delete store item', 'approve store item', 'View merchandise stock', 'insert merchandise recipient']

问题排查与修复

核心问题分析

  1. 组合并逻辑潜在漏洞:原代码虽用array_merge合并主组与附加组,但未做严格的空值校验,若additionalGroup为空或格式错误,会导致附加组未被纳入权限计算。
  2. 权限查询范围限制:原GetAccess仅查询指定模块下的组权限,附加组的权限若属于其他模块,当前模块的查询无法覆盖这些内容。
  3. 组名匹配一致性问题:若$config['access']中的组名与用户实际组名存在大小写、空格差异,会导致匹配失败,附加组权限无法被合并。

修复方案

1. 优化用户组合并逻辑

在GetRoles中增加空值判断与去重,确保所有有效组都被纳入计算:

public function GetRoles($id = 'new', $module = null) {
    $json = [];
    $groups = [];

    // 处理主组
    $mainGroup = $this->auth['payload']['group'] ?? null;
    if (!empty($mainGroup)) {
        $groups = array_merge($groups, (array)$mainGroup);
    }
    // 处理附加组
    $additionalGroups = $this->auth['payload']['additionalGroup'] ?? null;
    if (!empty($additionalGroups)) {
        $groups = array_merge($groups, (array)$additionalGroups);
    }
    // 去重避免重复组干扰
    $groups = array_unique($groups);

    // 传入null获取所有模块的权限
    $access = GetAccess($module ?? null, $groups);

    $json['insert']   = ($id === 'new' && in_array('insert', $access)) ? true : null;
    $json['view']     = ($id === 'view' && in_array('view', $access)) ? true : null;
    $json['update']   = ($id !== 'new' && in_array('update', $access)) ? true : null;
    $json['delete']   = ($id !== 'new' && in_array('delete', $access)) ? true : null;
    $json['upload']   = ($id !== 'new' && in_array('upload', $access)) ? true : null;
    $json['remove']   = ($id !== 'new' && in_array('remove', $access)) ? true : null;
    $json['inactive'] = ($id !== 'new' && in_array('inactive', $access)) ? true : null;
    $json['approve']  = ($id !== 'new' && in_array('approve', $access)) ? true : null;
    $json['cancel']   = ($id !== 'new' && in_array('cancel', $access)) ? true : null;
    $json['reopen']   = ($id !== 'new' && in_array('reopen', $access)) ? true : null;

    return $json;
}

2. 修改GetAccess支持全模块权限查询

调整GetAccess函数,增加全模块权限收集逻辑,当$module为null时遍历所有模块的权限配置:

function GetAccess($module = null, $groups, $role = null) {
    global $config;

    $rules   = [];
    $modules = ModuleMerge($config['modules']);

    if ($module === null) {
        // 遍历所有模块,收集用户所有组的权限
        foreach ($config['access'] ?? [] as $mod => $groupPermissions) {
            foreach ($groupPermissions as $key => $value) {
                if (in_array($key, $groups)) {
                    $rules = array_unique(array_merge($rules, $value));
                }
            }
        }
    } else if (isset($config['access'][$module])) {
        // 查询指定模块下的用户组权限
        foreach ($config['access'][$module] ?? [] as $key => $value) {
            if (in_array($key, $groups)) {
                $rules = array_unique(array_merge($rules, $value));
            }
        }
    } else if (in_array($module, ['main', 'login', 'login_google', 'register', 'reset', 'newpassword', 'validate', 'contact_us', 'disclaimer', 'privacy_policy', 'security_policy', 'terms_condition', 'help'])) {
        $rules = ['view', 'insert', 'update'];
    } else {
        $rules = $modules[$module] ?? [];
    }

    if ($role) {
        $rules = in_array($role, $rules);
    }

    return $rules;
}

3. 验证组名匹配一致性

检查$config['access']中的组名与用户实际组名是否完全一致(包括大小写、空格),例如确保'Store Admin'在配置中与用户组名完全相同,避免匹配失败。

修复效果验证

修复后,用户1的权限将合并所有所属组的权限,得到期望的结果:
['View main dashboard', 'edit profile', 'upload profile picture', 'View store module page', 'add store item', 'update store item', 'delete store item', 'approve store item', 'View merchandise stock', 'insert merchandise recipient']

内容的提问来源于stack exchange,提问作者Developer MBAS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:34:55