PHP权限系统核心是“用户-角色-权限”三层关系,需通过users、roles、permissions三张主表及user_roles、role_permissions两张关联表实现;登录后将权限加载至$_SESSION['permissions'],并封装can()函数进行校验,且须在路由层、操作层、展示层多点校验。

PHP权限系统的核心是“用户-角色-权限”三层关系,判断时关键不在于写多少代码,而在于理清数据结构和验证时机。只要角色与权限的绑定关系明确、每次请求前完成校验,权限控制就自然成立。
设计角色与权限的数据结构
权限系统要可维护,数据库设计必须清晰。通常用三张表:
- users:存用户基础信息(id、username、password_hash等)
- roles:存角色(如 admin、editor、viewer)
- permissions:存具体权限(如 post.create、user.delete、setting.view)
- 再加两张关联表:user_roles(用户→角色)、role_permissions(角色→权限)
不建议把权限直接存在用户表里——角色变动时要批量更新用户,容易出错;也不建议用位运算或JSON字段存权限——查询和调试困难。
登录后加载用户权限到会话
用户登录成功后,立刻查出他所有权限标识(如数组 ['post.create', 'post.edit']),并存入 $_SESSION['permissions']:
立即学习“PHP免费学习笔记(深入)”;
// 示例:根据用户ID获取权限列表
$userId = $_SESSION['user_id'];
$permissions = $pdo->prepare("
SELECT DISTINCT p.code
FROM permissions p
JOIN role_permissions rp ON p.id = rp.permission_id
JOIN user_roles ur ON rp.role_id = ur.role_id
WHERE ur.user_id = ?
");
$permissions->execute([$userId]);
$_SESSION['permissions'] = array_column($permissions->fetchAll(), 'code');
后续所有权限判断都基于这个数组,避免重复查库。注意:每次用户角色变更后,需主动清除该用户的 session 或更新其权限缓存。
封装通用权限判断函数
function can($permission): bool {
return isset($_SESSION['permissions'])
&& in_array($permission, $_SESSION['permissions']);
}
使用时非常直观:
if (!can('user.delete')) { die('无权操作'); }发布文章
进阶可支持通配符,比如 can('post.*') 匹配所有 post 相关权限,但基础阶段建议先用精确匹配,逻辑更可控。
在关键位置插入权限校验
权限判断不是只做一次,而是贯穿请求生命周期:
- 路由层:访问控制器方法前校验(适合 MVC 框架的中间件或基类构造函数)
- 操作层:执行敏感动作前再次确认(如删除用户前 check can('user.delete'))
- 展示层:模板中控制按钮/菜单是否显示(提升用户体验,但不能替代服务端校验)
记住:前端隐藏 ≠ 权限控制。所有关键操作必须在 PHP 后端重新验证,防止绕过。
基本上就这些。不复杂但容易忽略的是权限缓存更新和校验位置的选择——写对了,系统就稳;漏一处,就可能越权。











