每個權限點對應一個二進制位 (2ⁿ),用戶權限值 = 擁有權限位的 按位或 (|) 組合。判斷權限 = 用戶值 & 權限位 非零。
| 權限 | 位索引 (n) | 二進制 | 十進制值 |
|---|---|---|---|
| add | 1 | 0000 0001 | 1 |
| del | 2 | 0000 0010 | 2 |
| read | 3 | 0000 0100 | 4 |
| list | 4 | 0000 1000 | 8 |
| mod | 5 | 0001 0000 | 16 |
| detail | 6 | 0010 0000 | 32 |
| pub | 7 | 0100 0000 | 64 |
| collect | 8 | 1000 0000 | 128 |
用戶擁有 add|del|read → 值 = 1|2|4 = 7。
<?php
/**
* 二進制交叉權限微型類
* 支援:場景隔離、配置驅動、閉包批處理、陣列翻轉查找
*/
class s_allow {
public $scene; // 場景標識: 'access', 'cert', 'bind'
public $caseList = []; // 該場景所有權限定義 [位索引=>名稱]
public $allowValue = 0; // 用戶權限值 (位掩碼)
public $allowList = []; // 用戶擁有權限名稱列表
// 配置文件解析器 (簡化版,實際可用 parse_ini_file)
private static $configCache = [];
private static function config(string $scene, string $key) {
if (!isset(self::$configCache[$scene])) {
// 模擬讀取 ini 文件
$ini = [
'access' => ['add','del','read','list','mod','detail','pub','collect','like','send'],
'cert' => ['email','tel','qq','identity_card','real_name','business_license'],
'bind' => ['qq','weibo','taobao','alipay','renren','weichat','baidu'],
];
self::$configCache[$scene] = array_combine(range(1, count($ini[$scene])), $ini[$scene]);
}
return $key === 'allow' ? self::$configCache[$scene] : null;
}
public function __construct(string $scene, int $allowValue = 0) {
$this->scene = $scene;
$this->caseList = $this->caseList(true); // 獲取完整定義 [索引=>名稱]
if ($allowValue > 0) {
$this->allowValue = $allowValue;
$this->allowList = $this->allowList($allowValue, true);
}
}
// 獲取所有權限定義
public function caseList(bool $full = false): array {
$list = self::config($this->scene, 'allow');
return $full ? $list : array_keys($list); // 全量 或 僅索引
}
// 從權限值解析擁有權限列表
public function allowList(int $allowValue = 0, bool $full = false): array {
$value = $allowValue ?: $this->allowValue;
$buffer = [];
foreach ($this->caseList as $idx => $name) {
if ($value & (1 << ($idx - 1))) { // 位運算判斷
$buffer[$idx] = $name;
}
}
return $full ? $buffer : array_keys($buffer);
}
// 從權限名稱陣列計算權限值 (批處理 + 閉包)
public function allowValue(array $allowList = null): int {
$list = $allowList ?? $this->allowList;
array_walk($list, function(&$v, $k) { $v = 1 << ($k - 1); }); // 索引轉位值
return array_sum($list);
}
// 判斷是否擁有某權限
public function isAllow(string $case): bool {
$flipped = array_flip($this->caseList); // 名稱→索引
$idx = $flipped[$case] ?? 0;
return $idx > 0 && ($this->allowValue & (1 << ($idx - 1))) !== 0;
}
}
[access]
1=add
2=del
3=read
4=list
5=mod
6=detail
7=pub
8=collect
9=like
10=send
[cert]
1=email
2=tel
3=qq
4=identity_card
5=real_name
6=business_license
[bind]
1=qq
2=weibo
3=taobao
4=alipay
5=renren
6=weichat
7=baidu
<?php
require 's_allow.php';
// 1. 權限分配:用戶擁有 讀、寫、列表、發布
$access = new s_allow('access');
$userPerms = ['read', 'add', 'list', 'pub']; // 來自數據庫/配置
$userValue = $access->allowValue(array_flip($userPerms)); // 計算值:4|1|8|64 = 77
// 存入數據庫:permissions = 77
// 2. 權限驗證:從數據庫讀取值實例化
$userAccess = new s_allow('access', 77);
if ($userAccess->isAllow('add')) {
echo "✅ 允許新增";
}
if (!$userAccess->isAllow('del')) {
echo "❌ 禁止刪除";
}
// 3. 認證場景:用戶完成 郵箱、手機、實名 認證
$cert = new s_allow('cert', 0);
$certValue = $cert->allowValue(['email', 'tel', 'real_name']); // 1|2|5 = 1|2|16 = 19
// 4. 第三方綁定:用戶綁定 QQ、微信、支付寶
$bind = new s_allow('bind', 0);
$bindValue = $bind->allowValue(['qq', 'wechat', 'alipay']); // 1|6|4 = 1|32|8 = 41
// 5. 批量檢查 (陣列翻轉 O(1) 查找)
$required = ['read', 'mod', 'pub'];
foreach ($required as $perm) {
echo $perm . ': ' . ($userAccess->isAllow($perm) ? 'YES' : 'NO') . "\n";
}
<?php
class MultiScopeAuth {
// 位段分配:每場景佔 16 位 (支援 65535 個權限點)
const SHIFT = 16;
const MASK = 0xFFFF;
public static function encode(array $scopes): int {
$value = 0;
foreach ($scopes as $scene => $permValue) {
$value |= ($permValue & self::MASK) << ($scene * self::SHIFT);
}
return $value;
}
public static function decode(int $value, string $scene): int {
return ($value >> ($scene * self::SHIFT)) & self::MASK;
}
}
// 使用:將 access(16位) + cert(16位) + bind(16位) 合並為單一 48 位整數
$combined = MultiScopeAuth::encode([
0 => 77, // access
1 => 19, // cert
2 => 41, // bind
]);
// 存入單一字段:auth_bitmap = 18014398509481984... (大整數)
// 讀取時:
$accessVal = MultiScopeAuth::decode($combined, 0); // 77
| 優點 | 缺點 | 適用場景 |
|---|---|---|
| 極致緊湊:單整數存 64 權限 | 權限點超過 64 需大整數/多字段 | RBAC 核心權限、功能開關、功能授權 |
| 判斷極快:單次位運算 | 不可直接表達「否決/排除」邏輯 | 高頻檢查 (中間件、模板渲染) |
| 組合靈活:位或/位與/位異或 | 業務語義不直觀,需文檔/常量維護 | 多租戶功能開關、會員等級特權 |
| 無連表查詢:權限值隨用戶行存儲 | 權限變更需更新所有用戶值 | 靜態權限結構、低頻變更 |