权限值必须是2的幂次方,否则位运算判断会误触发;如write=3(0b011)时,用户权限5(0b101)与之按位与得1,错误判定有write权限;正确写法应为1

因为位运算能用一个整数存多个布尔状态,判断、增删权限都是 O(1) 操作,不查库、不遍历、不拼 SQL,天然适合高频权限校验场景。
权限值必须是 2 的幂次方,否则 & 判断会误触发
比如定义 READ = 1、WRITE = 2、DELETE = 4,对应二进制分别是 0b001、0b010、0b100——每位独占一个 bit。一旦写成 WRITE = 3(0b011),那用户权限值为 5(0b101,即 READ | DELETE)时,$user_perms & WRITE 会得 1,条件为真,但实际根本没给 WRITE 权限。
- 错误写法:
define('WRITE', 3)→ 后续所有&判断都不可信 - 安全写法:用左移生成,如
1 、<code>1 、<code>1 ,或直接写 <code>1、2、4、8 - 数据库字段注意:如果用
TINYINT存,最多支持 8 个权限;用INT最多 32 个;PHP 自身 int 无限制,但别超平台位宽
判断权限不能只写 if ($perms & $flag),组合权限时必须用 ==
单个权限(如 READ = 1)时,$perms & READ 非零即有,看似没问题。但一旦引入组合权限常量(如 ADMIN = READ | WRITE | DELETE),就容易翻车:
-
$perms & ADMIN返回的是交集值,比如用户只有READ | WRITE(=3),而ADMIN = 7,那么3 & 7 == 3,非零 → 条件成立,但其实缺DELETE - 正确写法:
($perms & ADMIN) === ADMIN,确保所有位都被置 1 - 同理,检查“是否至少拥有其中某几个”要用
($perms & ($a | $b)) !== 0,不是==
& ~ 移除权限时,别直接对 ~$flag 赋值
PHP 中 ~2 不是 0b101,而是 -3(补码表示,高位全 1),直接 $perms &= ~2 会意外清掉其他高位权限(尤其在 32/64 位整数环境下)。
- 错误:
$perms &= ~WRITE→ 在某些 PHP 版本或扩展下可能破坏高位 - 安全做法:加掩码,如
$perms &= ~WRITE & 0xFF(限制在低 8 位),或更通用的$perms &= ~WRITE & $mask,其中$mask是你实际使用的最大权限范围(如所有已定义 flag 的或值) - 推荐初始化时就固定位宽,比如统一用
uint32_t语义,用0xFFFFFFFF做全局掩码
真正难的不是写对一行 &,而是整个权限体系从定义、存储、序列化到跨语言交互时,始终守住“每位唯一、掩码可控、比较语义明确”这三条线。漏掉任意一条,上线后都可能表现为偶发性权限放行或拦截失败,且极难复现。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











