HOW TO SEND AJAX REQUEST WITH CSRF TOKEN IN CODEIGNITER
Cross-Site Request Forgery (CSRF) is a way to trick the server that a request sent to it is legitimate while it actually is an unauthorized attempt. In CodeIgniter, CSRF protection is not enabled by default. If it is been enabled then CodeIgniter generates a hash for each active user and this is used to verify the request. Require to send the hash with the AJAX request otherwise, it gives error – “The action you have requested is not allowed.”. In this tutorial, I show how you can enable CSRF protection and regenerate hash for next AJAX request and pass hash in AJAX request in the CodeIgniter project. In this example, I am using Enable CSRF protection – Open Open Default controller Open Load Database To access the MySQL database require loading Open Create a Create Check if Return the Completed Code Create Create 2 methods – Read POST values and assign in Assign return value in Return Completed Code Create Create a text element and store token name which is specified in Added some user names in the To display selected user details created Script – Define Read Assign selected option value in Send AJAX POST request to Here, hash will pass like – On successful callback read the token from Loop on the Completed Code Select a username from the dropdown. If you don’t want to regenerate hash for every AJAX then set Contents
1. Table structure
users
table and added some records –
CREATE TABLE `users` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` varchar(80) NOT NULL,
`username` varchar(80) NOT NULL,
`gender` varchar(10) NOT NULL,
`email` varchar(80) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. Configuration
application/config/config.php
file and update the values of $config['csrf_protection']
, $config['csrf_token_name']
, and $config['csrf_regenerate']
like this –
$config['csrf_protection'] = TRUE; // Enable CSRF
$config['csrf_token_name'] = 'csrf_hash_name'; // Token name (You can update it)
$config['csrf_regenerate'] = TRUE; // Set TRUE to regenerate Hash
TRUE
the $config['csrf_protection']
, this will enable CSRF.$config['csrf_token_name']
default it is set to 'csrf_test_name'
. I changed it to 'csrf_has_name'
. This name is used in AJAX request to pass the hash.TRUE
the $config['csrf_regenerate']
if you want to regenerate CSRF hash after each AJAX request otherwise set it FALSE
.application/config/database.php
and define the Database connection.
$db['default'] = array(
'dsn' => '',
'hostname' => 'localhost',
'username' => 'root', // Username
'password' => '', // Password
'database' => 'tutorial', // Database name
'dbdriver' => 'mysqli',
'dbprefix' => '',
'pconnect' => FALSE,
'db_debug' => (ENVIRONMENT !== 'production'),
'cache_on' => FALSE,
'cachedir' => '',
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE,
'failover' => array(),
'save_queries' => TRUE
);
application/config/routes.php
and edit default_controller
value to User
.
$route['default_controller'] = 'User';
database
library.application/config/autoload.php
and add the database
in libraries array()
.
$autoload['libraries'] = array("database");
3. Model
Main_model.php
file in the application/models/
directory.getUserDetails()
method which takes a single parameter.$postData['username']
is set or not. If set then fetch a record from users
table where username=$postData['username']
.$response
Array.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Main_model extends CI_Model {
function getUserDetails($postData){
$response = array();
if(isset($postData['username']) ){
// Select record
$this->db->select('*');
$this->db->where('username', $postData['username']);
$q = $this->db->get('users');
$response = $q->result_array();
}
return $response;
}
}
4. Controller
User.php
file in application/controllers/
directory.
url
helper and user_view
view.$postData
. Load Main_model
Model and call getUserDetails()
method where pass $postData
.$data
and read the new CSRF hash by calling $this->security->get_csrf_hash()
for next AJAX request and assign in $data['token']
.$data
Array in JSON format.
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class User extends CI_Controller {
public function index(){
// load base_url
$this->load->helper('url');
// load view
$this->load->view('user_view');
}
public function userDetails(){
// POST data
$postData = $this->input->post();
// load model
$this->load->model('Main_model');
// get data
$data = $this->Main_model->getUserDetails($postData);
// Read new token and assing in $data['token']
$data['token'] = $this->security->get_csrf_hash();
echo json_encode($data);
}
}
5. View
user_view.php
file in application/views/
directory.application/config.php
file in name
attribute using <?= $this->security->get_csrf_token_name(); ?>
. Store CSRF hash in the element by calling <?= $this->security->get_csrf_hash(); ?>
.<select > <option>
. Used username in the <option >
value.<span >
elements.change
event on #sel_user
selector.name
attribute of .txt_csrfname
selector and assign in csrfName
variable. Assign .txt_csrfname
selector value in csrfHash
variable.username
variable.'<?=base_url()?>index.php/User/userDetails'
where pass {username:username,[csrfName]:csrfHash }
as data
.[csrfName]: csrfHash
.response
and update the .txt_csrfname
selector value.response[0]
and update <span >
elements text.
<!doctype html>
<html>
<head>
<title>How to Send AJAX request with CSRF token in CodeIgniter</title>
</head>
<body>
<!-- CSRF token (Here, name is 'csrf_hash_name' which is specified in $config['csrf_token_name'] in cofig.php file ) -->
<input type="text" class="txt_csrfname" name="<?= $this->security->get_csrf_token_name(); ?>" value="<?= $this->security->get_csrf_hash(); ?>"><br>
Select Username : <select id='sel_user'>
<option value='yssyogesh'>yssyogesh</option>
<option value='sonarika'>sonarika</option>
<option value='vishal'>vishal</option>
<option value='sunil'>sunil</option>
</select>
<!-- User details -->
<div >
Username : <span id='suname'></span><br/>
Name : <span id='sname'></span><br/>
Email : <span id='semail'></span><br/>
</div>
<!-- Script -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type='text/javascript'>
// baseURL variable
var baseURL= "<?= base_url();?>";
$(document).ready(function(){
$('#sel_user').change(function(){
// CSRF Hash
var csrfName = $('.txt_csrfname').attr('name'); // Value specified in $config['csrf_token_name']
var csrfHash = $('.txt_csrfname').val(); // CSRF hash
// Username
var username = $(this).val();
// AJAX request
$.ajax({
url:'<?=base_url()?>index.php/User/userDetails',
method: 'post',
data: {username: username,[csrfName]: csrfHash },
dataType: 'json',
success: function(response){
// Update CSRF hash
$('.txt_csrfname').val(response.token);
// Empty the elements
$('#suname,#sname,#semail').text('');
// Loop on response
$(response[0]).each(function(key,value){
var uname = value.username;
var name = value.name;
var email = value.email;
$('#suname').text(uname);
$('#sname').text(name);
$('#semail').text(email);
});
}
});
});
});
</script>
</body>
</html>
6. Demo
7. Conclusion
FALSE
to $config['csrf_regenerate']
in config.php
file. In this case, the new hash will be generated according to the CSRF expiry time set.