Codeignter3 dengan Datatable dan CSRF Auto Regenerate

Codeignter3 dengan Datatable dan CSRF Auto Regenerate True

CSRF menurut wikipedia

Pemalsuan permintaan lintas situs, juga dikenal sebagai serangan satu kali klik atau sesi berkendara dan disingkat CSRF atau XSRF, adalah jenis eksploitasi berbahaya dari sebuah situs web di mana perintah yang tidak sah ditransmisikan dari pengguna yang dipercaya oleh aplikasi web.

Saat CSRF diaktifkan ketika load datatable pasti akan mengalami kendala (Error halaman 403 – Forbidden), itu dikarenakan kita tidak mengirim kode token yang benar. lalu apalagi jika csrf auto regenerate nya true ini berarti token csrf akan selalu berganti setiap request halaman yang baru. Jadi saat kita akan load datatable kita terlebih dahulu mengambil nilai token csrf yang aktif lalu kemudian dikirimkan saat request data.

Saya asumsikan anda telah mempunyai codeigniter3 dan telah mendownload datatable.
Ekstrak datatable dan jquery pada folder assets
Lakukan konfigurasi seperti berikut:
– Setting base_url di file config.php (application/config/config.php)

$config['base_url'] = 'http://localhost/ci3/';

– set csrf_protection ke true di file config.php (application/config/config.php)

$config['csrf_protection'] = TRUE;

– set csrf_regenerate ke true di file config.php (application/config/config.php)
– Aktifkan helper url dengan salah satu cara edit file autoload.php lalu masukan ‘url’ kedalam helper array, contohnya seperti berikut:

//load otomatis helper url
$autoload['helper'] = array('url');

Aktifkan libarary database dengan salah satu cara edit file autoload.php lalu masukan ‘database’ kedalam libarary array, contohnya seperti berikut:

//load otomatis library database
$autoload['libraries'] = array('database');

Pada contoh kali ini kita akan mencoba menampilkan data icd. download data icd dan lakukan import data kedalam database. download data icd dalam tutorial ini:

klik Integrasi Codeigniter 4 dengan Datatable Server Side

Membuat file controller

Icd.php

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Icd extends CI_Controller {

  public function index()
  {
    $this->load->view('icd');
  }

  public function ajax_list()
  {
    $csrf_name = $this->security->get_csrf_token_name();
    $csrf_hash = $this->security->get_csrf_hash();  
    $this->load->model("model_icd","model");
    if($this->input->method(TRUE)=='POST'):
      $list = $this->model->get_datatables();
          $data = array();
          $no = $this->input->post('start');
          $now = strtotime(date("Y-m-d"));
          foreach ($list as $data1) {
              	$no++;
                  $row = array();
                  $row[] = $no;
                  $row[] = $data1->kode_icd;
                  $row[] = $data1->nama_icd;
                  $data[] = $row;
      }
      $output = array(
                          "draw" => $this->input->post('draw'),
                          "recordsTotal" => $this->model->count_all(),
                          "recordsFiltered" => $this->model->count_filtered(),
                          "data" => $data,
                  );
      $output[$csrf_name] = $csrf_hash;  
          //output to json format
          echo json_encode($output);
    endif;
  }

}

Membuat file model

Model_icd.php

<?php

class Model_icd extends CI_Model{
  public $table = "tbl_icd";
  var $column_order = array('id_icd','kode_icd','nama_icd');
    var $column_search = array('id_icd','kode_icd','nama_icd');
    var $order = array('tbl_icd.id_icd' => 'desc');

  function __construct()
  {
    parent::__construct();
  }

  private function _get_datatables_query()
    {
        $from = $this->db->from($this->table);
 
        $i = 0;
     
        foreach ($this->column_search as $item)
        {
            if($this->input->post('search')['value'])
            {
                 
                if($i===0)
                {
                    $this->db->group_start();
                    $this->db->like($item, $this->input->post('search')['value']);
                }
                else
                {
                    $this->db->or_like($item, $this->input->post('search')['value']);
                }
 
                if(count($this->column_search) - 1 == $i)
                    $this->db->group_end();
            }
            $i++;
        }
         
        if($this->input->post('order'))
        {
            $this->db->order_by($this->column_order[$this->input->post('order')['0']['column']], $this->input->post('order')['0']['dir']);
        } 
        else if(isset($this->order))
        {
            $order = $this->order;
            $this->db->order_by(key($order), $order[key($order)]);
        }
    }
 
    public function get_datatables()
    {
        $this->_get_datatables_query();
        if($this->input->post('lengt') != -1)
        $this->db->limit($this->input->post('length'), $this->input->post('start'));
        $query = $this->db->get();
        return $query->result();
    }
 
    public function count_filtered()
    {
        $this->_get_datatables_query();
        $query = $this->db->get();
        return $query->num_rows();
    }
 
    public function count_all()
    {
        $query = $this->db->from($this->table);
        return $this->db->count_all_results();
    }

}

Membuat file view

icd.php

<!DOCTYPE html>
<html>
<head>
  <title>Demo icd</title>
  <link rel="stylesheet" type="text/css" href="<?php echo base_url("assets/datatable/datatables.min.css");?>" />
  <link rel="stylesheet" type="text/css" href="<?php echo base_url("assets/bootstrap/css/bootstrap.min.css");?>" />
  <!-- masukan jquery karena datatable adalah plugin jquery -->
  <script src="<?php echo base_url("assets/jquery.min.js");?>"></script>
</head>
<body>
<div class="container">
  <table id="myTable" class="table table-striped table-bordered table-hover">
    <thead><tr><td>No</td><td>Kode ICD</td><td>Nama ICD</td></tr></thead>
    <tbody>
    </tbody>
  </table>
</div>
<script type="text/javascript">
$(document).ready( function () {
  var token = "<?php echo $this->security->get_csrf_hash();?>";
  var table = $('#myTable').DataTable({ 

    "processing": true,
    "serverSide": true,
    "order": [],

    "ajax": {
        "url": "<?php echo base_url('icd/ajax_list')?>",
        "type": "POST",
        data: function ( d ) {
         d.<?php echo $this->security->get_csrf_token_name();?> = token;
       }
    },

    //optional
    "lengthMenu": [[5, 10, 25], [5, 10, 25]],

    "columnDefs": [
    { 
        "targets": [0,1,2],
        "orderable": true,
    },
    ],

});

   table.on('xhr.dt', function ( e, settings, json, xhr ) {
        token = json.<?=$this->security->get_csrf_token_name();?>;
    } );

} );
</script>

<script src="<?php echo base_url("assets/datatable/DataTables-1.10.20/js/jquery.dataTables.min.js");?>"></script>

<script src="<?php echo base_url("assets/datatable/datatables.min.js");?>"></script>

</body>
</html>

Untuk menghilangkan index.php buat file .htaccess isikan script sebagai berikut dan simpan didalam folder root codeigniter:

RewriteEngine On
RewriteCond $1 !^(index\.php|resources|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

Kesimpulannya saat pertama kali load datatable csrf token dikirimkan melalui parameter pada datatable yaitu

data: function ( d ) {
         d.<?php echo $this->security->get_csrf_token_name();?> = token;
         }

Yang dimana nilai token didapat dari fungsi class security dari codeigniter yaitu

<?php echo $this->security->get_csrf_hash();?>

untuk

<?php echo $this->security->get_csrf_token_name();?>

adalah nama tokennya. untuk mendapatkan nilai token terbaru didapat dari hasil json pada controller lalu dimasukan kedalam variable javascript seperti:

table.on('xhr.dt', function ( e, settings, json, xhr ) {
        token = json.<?=$this->security->get_csrf_token_name();?>;
    } );

Setelah itu coba jalankan aplikasi http://localhost/ci3/icd

Refrensi codeigniter3 security https://codeigniter.com/userguide3/libraries/security.html

Related posts

Leave a Comment