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

CRUD系统中如何获取用户权限?

权限获取优化方案

针对你的需求,这里提供几个实用的优化方向:

1. 精简Session存储的权限数据

你当前的代码会把权限表的所有字段存入Session,体积冗余且没必要。可以只提取关键权限标识,转成键值对结构存储,大幅压缩存储体积:

// 优化SQL,只查询需要的权限字段,避免SELECT *
$permissions = sqlSelect($conn, '
SELECT permissions.key, permissions.value 
FROM permissions
INNER JOIN roles ON permissions.role_id = roles.id
INNER JOIN users_role ON permissions.role_id = users_role.role_id
WHERE users_role.user_id = ?', 'i', $row['id']);

$user_permissions = [];
while ($permission_row = $permissions->fetch_assoc()) {
    // 转成键值对,比如 $user_permissions['can_edit'] = true
    $user_permissions[$permission_row['key']] = $permission_row['value'];
}

$_SESSION['logged'] = true;
// 存储精简后的权限,体积大幅减小
$_SESSION['user_permissions'] = $user_permissions;

如果权限是布尔型或固定枚举值,还可以用位掩码进一步压缩:把每个权限映射成一个二进制位,最终用一个整数表示所有权限(12个权限仅需一个int字段存储),读取时通过位运算判断权限状态。

2. 使用缓存中间件替代Session

用Redis、Memcached这类缓存工具存储权限数据,相比Session优势明显:

  • 存储容量更大、读写性能更高
  • 可设置合理过期时间(比如登录后2小时自动过期,过期重新加载)
  • 支持分布式部署,适配多服务器场景

示例代码(Redis):

// 连接Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// 生成唯一缓存键
$cacheKey = 'user_perms_' . $row['id'];

// 优先从缓存读取
$user_permissions = $redis->get($cacheKey);
if (!$user_permissions) {
    // 缓存不存在时查询数据库
    $permissions = sqlSelect($conn, '
    SELECT permissions.key, permissions.value 
    FROM permissions
    INNER JOIN roles ON permissions.role_id = roles.id
    INNER JOIN users_role ON permissions.role_id = users_role.role_id
    WHERE users_role.user_id = ?', 'i', $row['id']);

    $user_permissions = [];
    while ($permission_row = $permissions->fetch_assoc()) {
        $user_permissions[$permission_row['key']] = $permission_row['value'];
    }

    // 存入缓存,设置2小时过期
    $redis->setex($cacheKey, 7200, json_encode($user_permissions));
} else {
    $user_permissions = json_decode($user_permissions, true);
}

// 可选:把精简后的权限存入Session,后续直接从Session读取
$_SESSION['user_permissions'] = $user_permissions;

3. 按需加载权限模块

如果权限按业务模块划分(比如用户管理、订单管理),可以只在用户进入对应模块时加载该模块权限,而非一次性全量加载:

// 封装模块权限查询函数
function getModulePermissions($conn, $userId, $module) {
    $permissions = sqlSelect($conn, '
    SELECT permissions.key, permissions.value 
    FROM permissions
    INNER JOIN roles ON permissions.role_id = roles.id
    INNER JOIN users_role ON permissions.role_id = users_role.role_id
    WHERE users_role.user_id = ? AND permissions.module = ?', 'is', [$userId, $module]);

    $modulePerms = [];
    while ($permission_row = $permissions->fetch_assoc()) {
        $modulePerms[$permission_row['key']] = $permission_row['value'];
    }
    return $modulePerms;
}

// 使用示例:用户进入订单管理页面时加载订单权限
$orderPerms = getModulePermissions($conn, $row['id'], 'order');
$_SESSION['order_permissions'] = $orderPerms;

4. 优化数据库查询效率

  • 给users_role.user_id、permissions.role_id、roles.id这些关联字段建立索引,加快关联查询速度
  • 严格避免SELECT *,只查询业务需要的字段,减少数据传输量

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:23:41