Kỹ thuật bit field trong phân quyền
Bài viết này sẽ hướng dẫn cho các bạn áp dụng kỹ thuật bit field trong phân quyền chức năng ứng dụng.
Mở đầu
Ý tưởng là dùng các bit để lưu trạng thái, hoặc phân quyền trong chương trình. Với cách lưu này thì mỗi trạng thái chỉ tốn 1 bit để lưu trữ. Vi dụ ta lưu 4 quyền view/add/edit/delete theo một dãy 0-1, được lưu trong một biến kiểu int. (Với kiểu int32 ta có thể lưu tối đa 32 trạng thái).
Full control (15):
Delete |
Edit |
Add |
View |
1 |
1 |
1 |
1 |
Tương ứng, ta lưu các quyền với các giá trị như sau:
Base |
Delete |
Edit |
Add |
View |
Binary |
1000 |
100 |
10 |
1 |
Bitwise |
1 << 3 |
1 << 2 |
1 << 1 |
1 << 0 |
Decimal |
8 |
4 |
2 |
1 |
Bây giờ ta có các quyền được thể hiện như sau:
view = 1
view + add = 1 + 2 = 3
view + add + edit = 1 + 2 + 4 = 7
view + add + edit + delete = 1 + 2 + 4 + 8 = 15
Chẳng hạn khi cần kiểm tra user có quyền edit hay không, ta chỉ cần lấy quyền của user và AND với giá trị edit (4) nếu nó khác 0 (và bằng chính quyền đó, trong trường hơp edit là 4) là user có quyền thực hiện quyền này.
Bảng các quyền tương ứng với cơ số 10:
Edit-Add-View (7)
Delete |
Edit |
Add |
View |
0 |
1 |
1 |
1 |
Add-View (3)
Delete |
Edit |
Add |
View |
0 |
0 |
1 |
1 |
View (1)
Delete |
Edit |
Add |
View |
0 |
0 |
0 |
1 |
Ví dụ
Giả sử module tin tức trong ứng dụng của mình có 4 chức năng:
- Đọc tin
- Thêm tin
- Xóa tin
- Sửa tin
Mình cần phân quyền cho 2 nhóm: admin và editor
Áp dụng kỹ thuật bit field, mình sẽ cho mỗi chức năng của module tin tức 1 con số đại diện, và lưu thành mảng:
- $bitfields_news = array(
- 'canview' => 1,
- 'canadd' => 2,
- 'canedit' => 4,
- 'candelete' => 8);
Các bạn để ý các con số đại diện, tăng theo qui luật, số sau = số trước x 2 (bắt đầu từ 1)
Trong table groups, mình có cột news_permission, cột này sẽ cho biết admin hay editor có những quyền gì.
Giả sử admin có full quyền thì cột news_permission sẽ có giá trị:
1 + 2 + 4 + 8 = 15
Giả sử editor chỉ có quyền xem và sửa thì cột news_permission sẽ có giá trị:
1 + 4 = 5
Bảng groups sẽ như sau:
id_____name______news_permission
1_____admin______15
2_____editor______5
Bây giờ, ta sẽ xét quyền. Khi user nhấn delete một mẩu tin nào đó, ta sẽ check như sau:
- if ($users['Group']['news_permission'] & 8) {
-
- }
Chú ý phép toán &
Các bạn có thể dùng hàm decbin() để đổi sang nhị phân rồi đối chiếu
- decbin(15) = 1111
- decbin(8) = 1000
Mã nguồn forum VBB sử dụng kỹ thuật này rất hiệu quả
Ví dụ code mẫu:
- <?php
- class bitmask
- {
-
-
-
-
-
-
-
-
- public $permissions = array(
- "read"=>false,
- "write"=>false,
- "delete"=>false,
- "change_permissions"=>false,
- "admin"=>false
- );
-
-
-
-
-
-
-
-
-
- publicfunction getPermissions($bitMask =0)
- {
- $i =0;
- foreach($this->permissions as $key => $value)
- {
- $this->permissions[$key]=(($bitMask & pow(2, $i))!=0)?true:false;
-
-
- $i++;
- }
- return $this->permissions;
- }
-
-
-
-
-
-
-
-
- function toBitmask()
- {
- $bitmask =0;
- $i =0;
- foreach($this->permissions as $key => $value)
- {
-
- if($value)
- {
- $bitmask += pow(2, $i);
- }
- $i++;
- }
- return $bitmask;
- }
- }
- ?>
Lưu vào cơ sở dữ liệu:
-
- <?php
-
-
-
-
- $perms =new bitmask();
-
-
-
-
- $perms->permissions["read"]=true;
- $perms->permissions["write"]=true;
- $perms->permissions["delete"]=true;
- $perms->permissions["change_permissions"]=true;
- $perms->permissions["admin"]=false;
-
-
- $bitmask = $perms->toBitmask();
- $sql ="insert into user_permissions (userid,permission) values(1,$bitmask)";
- echo $sql;
- ?>
Xuất giá trị:
- <?php
-
-
-
-
- $permarr = $perms->getPermissions($bitmask);
-
- if($permarr["read"])
- {
- echo 'user can read: <font color="green">TRUE</font>';
- }else{
- echo 'user can read: <font color="red">FALSE</font>';
- }
-
-
- if($permarr["write"])
- {
- echo '<br>user can write: <font color="green">TRUE</font>';
- }else{
- echo '<br>user can write: <font color="red">FALSE</font>';
- }
-
- ?>
[Nghean-Aptech st]
Các tin mới hơn:
Hướng dẫn tích hợp giao diện trang quản trị SB Admin 2 vào Laravel 5.8.
Hướng dẫn tích hợp Google ReCaptcha v2 vào Laravel bằng curl.
Học lập trình React JS trong vòng 5 phút.
Sử dụng trình soạn thảo CKeditor tích hợp CKFinder với Laravel.
Hướng dẫn cài đặt Apache, PHP, MySQL, PHPMyAdmin trên Windows 10 và cấu hình SendMail.
Các tin cũ hơn:
Lựa chọn mô hình lập trình ASP.NET.
Giới thiệu nền tảng Windows Azure.
So sánh công nghệ Java và .Net.
Tại sao cần tránh viết SQL code trong ứng dụng?.
ASP.NET MVC - Truy xuất dữ liệu từ Controller.