Apa itu RBAC? RBAC (Role Based Access Control) adalah suatu pendekatan dalam mengatur hak akses user terhadap aplikasi atau sistem (user authorization) berbasis role, sederhananya adalah pengaturan hak akses. Membahas ataupun mengimplementasikan hak akses adalah hal umum dan biasa dalam membangun aplikasi, tetapi kadang kita bingung untuk menentukan pakemnya. Bahkan cenderung kita hanya mengikut kebiasaan – kebiasaan yang ada dilapangan. Tidak jarang, kita hanya meng-klasifikasikan akses user berdasarkan group user saja seperti admin dan user. Tetapi, kita tidak menentukan permission apa saja yang dimiliki atau dapat diakses oleh user. Sehingga aplikasi menjadi tidak cukup secure. Nah, di artikel kali ini, penulis mencoba untuk memberikan sedikit gambaran tentang bagaimana membangun sistem access control sederhana yang dapat diimplementasikan dalam aplikasi berbasis web menggunakan PHP. Sistem yang akan kita buat tidaklah harus serumit sistem RBAC yang banyak dituturkan di website – website tetapi setidaknya dapat menjadi referensi dan praktek sederhana (plain de-facto).

Requirements

Untuk membangun sistem hak akses yang berbasis role (RBAC), minimal dibutuhkan 3 sampai 4 tabel yang digunakan untuk menyimpan data Roles, Permissions, Users, Roles Profiling dan Users Profiling. Jika diperlukan, ditambah tabel Group jika hak akses akan ditempelkan terhadap group bukan user. Keuntunganya, hak akses dapat diterapkan terhadap beberapa user dalam satu group sehingga lebih mudah dalam pemberian hak akses.

Roles

Roles dapat diartikan sebagai user responsibility. Kadang, pendefinisian jenis – jenis role mirip dengan nama group walaupun harusnya dibedakan dan lebih mirip kepada nama tanggung jawabnya. Misal: finance, inventory, dba (database admin) dll.

Contoh DDL:

CREATE TABLE `roles` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Users

Untuk kebutuhan yang satu ini penulis tidak akan jelaskan secara detail. Penulis hanya akan memberikan contoh DDL sederhana yang dapat dikembangkan sesuai kebutuhan.

CREATE TABLE `users` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) DEFAULT NULL,
  `user_pass` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Permission

Bagian ini merupakan bagian yang cukup unik. Sebagian besar konsentrasi perancangan sistem hak akses berada pada tahap ini. Konsepnya dapat sangat dinamis dan berbeda – beda satu sama lain, tergantung banyak faktor mulai dari pemahaman, sisi developer, kebutuhan, dan pertimbangan – pertimbangan lain. Bagian ini merupakan bagian penentu dari sistem hak akses, karena di sini di atur apa saja yang dapat diakses oleh masing – masing user. Misal: can_insert, can_update dll. Setiap permission didaftar dan kemudian divalidasi ketika user melakukan sesuatu terhadap sistem. Membuat daftar permission bisa jadi menjadi hal yang sangat rumit dan bisa jadi tidak konsisten karena tidak adanya suatu aturan. Hal ini tentunya akan mempersulit proses validasi-nya.

Contoh DDL:

CREATE TABLE `permissions` (
  `perm_id` int(11) NOT NULL AUTO_INCREMENT,
  `perm_name` varchar(255) DEFAULT NULL,
  `perm_module` varchar(255) DEFAULT NULL,
  `perm_action` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`perm_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Berdasarkan DDL di atas, kita akan membuat sebuah mekanisme pendataan dynamic permission berdasarkan module dan action. Sebagai contoh, sebuah file controller berisi metode – metode CRUD (create-read-update-delete).

namespace App\Controller;
 
class Product extends \Mvc\Controller {
 
  /**
   * Create product
   */
  public function createAction() {
 
  }
 
  /**
   * Read product
   */
  public function readAction() {
 
  }
 
  /**
   * Update product
   */
  public function updateAction() {
 
  }
 
  /**
   * Delete product
   */
  public function deleteAction() {
 
  }
 
}

Setiap method dalam sebuah controller dapat diakses menggunakan URL yang sesuai dengan definisi route (dalam paradigma MVC) atau mekanisme lain yang ditentukan. Ketika user mengakses URL /product/create, aplikasi akan menjalankan createAction(). Dari sini, kita mendapatkan gambaran sederhana bagaimana membuat data permission dengan cara yang cukup dinamis yaitu dengan mendata method apa saja yang ada di dalam sebuah controller. Tapi bagaimana caranya? Dalam PHP hal ini cukup simple. Kita dapat menggunakan fungsi token_get_all() atau yang lebih canggih dengan memanfaatkan ReflectionClass sehingga kita dapat mem-parsing anotasi setiap method lebih mudah.

$reflector = new \ReflectionClass('App\Controller\Product');
$class = $reflector->getName();
$methods = $reflector->getMethods();
$permissions = array();
 
foreach($methods as $method) {
 
  $comment = $reflector->getMethod($method->name)->getDocComment();
  $action = $class.'\\'.$method->name;
  $name = $action;
 
  if ($comment) {
    $lines = explode("\n", $comment);
    if (isset($lines[1])) {
      $name = trim(str_replace('*', '', $lines[1]));
    }
  }
 
  $permissions[] = array(
    'perm_name' => $name,
    'perm_module' => $class,
    'perm_action' => $method->name
  );
}
 
print_r($permissions);

Berikut contoh output-nya:

Array
(
    [0] => Array
        (
            [perm_name] => Create product
            [perm_module] => App\Controller\Product
            [perm_action] => createAction
        )
 
    [1] => Array
        (
            [perm_name] => Read product
            [perm_module] => App\Controller\Product
            [perm_action] => readAction
        )
 
    [2] => Array
        (
            [perm_name] => Update product
            [perm_module] => App\Controller\Product
            [perm_action] => updateAction
        )
 
    [3] => Array
        (
            [perm_name] => Delete product
            [perm_module] => App\Controller\Product
            [perm_action] => deleteAction
        )
 
)

Roles Profiling

Roles profiling digunakan sebagai intermediate table (has-many-to-many) yang memetakan antara role dan permission. Sehingga setiap role dapat memiliki konfigurasi beberapa permission.

Contoh DDL:

CREATE TABLE `roles_permissions` (
  `role_id` int(11) DEFAULT NULL,
  `perm_id` int(11) DEFAULT NULL,
  KEY `fk1` (`role_id`),
  KEY `fk2` (`perm_id`),
  CONSTRAINT `fk1` FOREIGN KEY (`role_id`) REFERENCES `roles` (`role_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk2` FOREIGN KEY (`perm_id`) REFERENCES `permissions` (`perm_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Users Profiling

Sama seperti roles-profiling, profiling ini digunakan sebagai intermediate table yang memetakan user dengan role. Sehingga satu user bisa memiliki beberapa role.

Contoh DDL:

CREATE TABLE `users_roles` (
  `user_id` int(11) DEFAULT NULL,
  `role_id` int(11) DEFAULT NULL,
  KEY `fk3` (`user_id`),
  KEY `fk4` (`role_id`),
  CONSTRAINT `fk3` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk4` FOREIGN KEY (`role_id`) REFERENCES `roles` (`role_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Validasi

Misal, ketika seorang user mengakses URL /product/create maka sistem akan memanggil class App\Controller\Product untuk menjalankan method createAction(). Sebelum method dijalankan, periksa dalam daftar hak akses. Untuk mendapatkan data hak akses, maka diperlukan memeriksa role yang aktif saat ini.

Misal:

SELECT *
FROM
    permissions a
    JOIN roles_permissions b ON (a.perm_id = b.perm_id)
    JOIN roles c ON (b.role_id = c.role_id)
    JOIN users_roles d ON (c.role_id = d.role_id)
    JOIN users e ON (d.user_id = e.user_id)
WHERE
    e.user_name = 'john'
    AND c.role_name IN ('finance')
    AND a.perm_module = 'App\\Controller\\Product'
    AND a.perm_action = 'createAction'

Jika ditemukan hasilnya, maka dikatakan user dimaksud memiliki akses ke method yang di-request.

Demikian gambaran singkat tentang teknik pembuatan sistem hak akses berbasis RBAC. Insyaallah, pada artikel berikutnya penulis akan menuliskan contoh implementasinya. Terima kasih dan ditunggu komentarnya.

Advertisements