在企業級後台管理系統中,權限控制是核心需求。本文採用「模組-功能」兩級架構,結合二進制字串儲存,實現高效、靈活的 RBAC(角色基礎存取控制)機制。適用於部門分級、職位階層等複雜業務場景。
RoleAction 欄位(VARCHAR),儲存二進制字串(如 "10110...")每個 Function 擁有唯一 FuncNo(從 1 開始),對應二進制字串的索引位置。1 表示擁有權限,0 表示無權限。
使用 Literal 控件輸出 HTML 表格,行為 Module,列為 Function。關鍵邏輯:
// 後台 BindAllModule() 摘要
StringBuilder sb = new StringBuilder();
sb.Append("<table class='AddRole'>");
// 遍歷 Module,產生 <tr><th>ModuleName</th><td>{ModuleID}</td></tr>
// 收集所有 ModuleID 字串 "1,2,3,"
if (Request.QueryString["nid"] != null) { // 編輯模式
BindAllFunction(moduleIdStr, sb, existingRoleActions);
} else { // 新增模式
BindAllFunction(moduleIdStr, sb, "");
}
LiteralRole.Text = sb.ToString();
BindAllFunction 根據 RoleActions 二進制字串,決定每個 CheckBox 是否 checked="checked"。
<script>
function getcheck() {
var inputs = document.getElementById("cbpanel");
var chks = inputs.getElementsByTagName("input");
var str = "";
for (var i = 0; i < chks.length; i++) {
if (chks[i].type == 'checkbox') {
// 格式:FuncNo,checked|FuncNo,checked|...
str += chks[i].value + "," + chks[i].checked + "|";
}
}
document.getElementById("Hidden1").value = str;
}
</script>
提交時,Hidden1.Value 送至後台,格式範例:"1,true|2,false|3,true|"
private string GenerateRoleAction(string str) {
DataTable dt = new DataTable();
dt.Columns.Add("funno", typeof(int));
dt.Columns.Add("flag");
// 解析前端傳來的 "FuncNo,checked|..." 格式
string[] items = str.TrimEnd('|').Split('|');
foreach (var item in items) {
var parts = item.Split(',');
DataRow dr = dt.NewRow();
dr[0] = parts[0]; // FuncNo
dr[1] = parts[1]; // true/false
dt.Rows.Add(dr);
}
// 按 FuncNo 排序,確保位置固定
dt.DefaultView.Sort = "funno asc";
DataTable sorted = dt.DefaultView.ToTable();
// 組裝二進制字串
StringBuilder sb = new StringBuilder();
foreach (DataRow row in sorted.Rows) {
sb.Append(row["flag"].ToString().ToLower() == "true" ? "1" : "0");
}
return sb.ToString(); // 如 "1011001..."
}
在 BindAllFunction 中,根據 RoleActions.Substring(FuncNo - 1, 1) 判斷該位是 '1' 還是 '0',動態輸出 CheckBox 的 checked 狀態。
| 優點 | 缺點/限制 |
|---|---|
| 儲存極度緊湊,單一 VARCHAR 即可容納數百權限 | Function 新增/刪除會導致位移,需重新編碼所有角色 |
| 查詢效能極高,無需多表 JOIN | 不支援多層級權限繼承(需額外邏輯) |
| 前後端交互資料量極小 | FuncNo 必須連續、不可重複,維護成本隨規模增長 |
BitArray 或 BigInteger 替代字串操作,提升效能