2010-05-30 66 views
4

我已經開始在我的MVC框架中開發一個PHP應用程序的論壇應用程序,並且我已經到了爲成員分配權限的階段(例如:READ,WRITE,UPDATE,DELETE)。我該如何實現論壇特權

現在,我知道我可以在我的數據庫中的用戶表下添加5列,並將它們設置爲1 | 0,但對我來說,如果我想添加其他規則,例如MOVE,則對我來說似乎太多了。

我該如何動態地將這些權限分配給用戶?

我聽說過使用位掩碼,但如果在我繼續之前能夠完全理解它們,那將非常好。

你有沒有我如何實現這個的例子?

回答

3

您描述的方法 - 存儲在列中的個人權限 - 以犧牲靈活性爲代價(如您注意到的)。

Zuul的方法更加簡單,與您的方法基本相同,只是它避免了任何「ALTER TABLE」語句的需要。但是,它不是標準化的,不容易查詢,也不能自我記錄。

這兩種方法的另一個問題是,隨着您的用戶羣的增長,您會發現越來越難以保證每個人的權限設置正確。你會發現自己有很多需要完全相同特權的用戶。但爲了改變用戶的權限,例如爲了適應新的權限,您必須進入併爲每個單獨需要它的用戶添加該權限。主要PITA。

對於論壇,您不太可能需要按用戶權限管理。更可能的是,您將擁有某些類別的用戶,如匿名用戶,登錄用戶,管理員,管理員等。這將使其非常適合基於角色的訪問控制(RBAC)。在這個系統中,您將爲每個用戶分配一個角色,並授予角色權限。特權將作爲行存儲在「特權」表中。所以簡化的數據庫模式將如下所示:

PRIVILEGE 
int id (primary key) 
varchar description 

ROLE_PRIVILEGE_JOIN 
privilege_id (foreign key) 
role_id (foreign key) 

ROLE 
int id (primary key) 
varchar description 

USER 
int id (primary key) 
int role_id (foreign key) 

此模式用於許多處理用戶權限的應用程序。添加任何人可能擁有的特權表作爲特權表中的一行;添加任何用戶可能在角色表中的每個角色;並在role_privilege_join表中適當地鏈接它們。

唯一真正的缺點是因爲使用了連接表,所以「can用戶X做Y」查詢會稍微慢一些。

+0

很好的描述了位掩碼和魔法字符串的缺陷。 – itchi 2010-05-30 03:05:05

+0

Thankyou爲此,我正在考慮咬口罩,因爲它還沒有完全掌握,我認爲我應該確切地知道它們是什麼以及它們是如何工作的,然後才能對權限系統的工作方式做出明確的決定,但是現在你把它放在上下文中,不需要一個位掩碼,因爲它只是在應用程序內複合一個簡單的任務,另外,當涉及到ACP中的privs管理時,它可以輕鬆地進行排序。謝謝 – RobertPitt 2010-05-30 13:45:34

-1

你並不需要複雜的是,只使用一個字段 「恩:權限」,並做一些事情,如:

$權限= 「1; 1; 0; 1」;

凡在你的關注記載:

READ - 1(罐)

WRITE - 1(可以)

更新 - 0(也不能)

DELETE - 1(可)

然後,當檢查時,只需使用「爆炸」的「;」... ...

這樣,您可以隨時應用更多的權限類型而無需更改您的表格......因此,您可以縮小表格,並更快地查詢您的表格!

這是你的問題:)的解決方法時,作爲二進制表示

+1

這裏的分號看起來沒有必要,因爲每個權限位只是一個字符。當你在存儲二進制字符串的時候,爲什麼不把它作爲一個小數點來存儲,前面所述的位掩碼原理呢? – Matchu 2010-05-30 02:36:43

+0

是的,你的權利!這是一個例子,也許不是最好的例子,但是被「;」分隔的價值將使您在將來添加像1; 0; 1; 1a; 0;等權限。 < - (1a是「罐」與級別「a」),但你可以再次使用12,其中「2」將是子級... – Zuul 2010-05-30 02:47:35

4

權限位掩碼是最好的理解,與代表許可被開啓或關閉每個數字。因此,如果權限X,Y和Z存在,並且我只能訪問X和Z,則101將表示我擁有授予我的第一個和第三個權限,但不是第二個。二進制數101相當於十進制數5,所以這將最終存儲在數據庫中。單個小整數是比一個或多個小整數更有效的存儲對象。

編輯:我意識到利用現有的轉換函數來實現相當快速的實現是多麼容易。這是一個示例。

<?php 
function bitmask_expand($n) { 
    // 9 returns array(1, 0, 0, 1) 
    return str_split(base_convert($n, 10, 2)); 
} 

function bitmask_compact($a) { 
    // array(1, 0, 0, 1) returns 9 
    return (int) base_convert(implode($a), 2, 10); 
} 

$ns = range(0, 7); 
foreach($ns as $n) { 
    print_r($b = bitmask_expand($n)); 
    echo bitmask_compact($b), "\n\n"; 
} 

,如果你使用的循環,而不是拉了回來,並從字符串你可能會得到更好的性能,但是這說明相當清楚的原則。

1

我想創建一個名爲「角色」表:

CREATE TABLE Roles(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY(id), 
rolename VARCHAR(30)) 

棒的任何權限,你在那裏想。然後創建一個名爲「的UserRole」鏈接的用戶角色表:

CREATE TABLE UserRoles(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY(id), 
UserId INT, 
RoleID INT) 

很多的靈活性和易於建立在(即工作流程,規則等) (我想補充外鍵以及)

+0

我認爲這對於OP想要的東西有點矯枉過正。一個簡單的位掩碼就可以做到。 – 2010-05-30 02:43:34

+0

我想我應該問他的應用程序的範圍和大小。 PhpBB使用phpbb_user_group表實現了類似的結構.. http://www.phpbbdoctor.com/doc_tables.php – itchi 2010-05-30 02:57:09