Security is always a primary agenda of application development. CSRF (Cross-Site Request Forgery) token is one of a very common security technique we use for malicious attacks.
A common PHP Framework like CodeIgnitor also has that feature. From CI v2.0 it has been introduced. We need to follow some steps to use the automated CSRF Token feature in our own CI applications.
- In the configuration file set $config[‘csrf_protection’] to true
- Use form_open() to start a form
These two steps will automatically add a hidden field with CSRF token in the form, and when a POST data encountered the cookie automatically validates the Input class.
*For more customization to CSRF you may check this lines on the config file
/* |-------------------------------------------------------------------------- | Cross Site Request Forgery |-------------------------------------------------------------------------- | Enables a CSRF cookie token to be set. When set to TRUE, token will be | checked on a submitted form. If you are accepting user data, it is strongly | recommended CSRF protection be enabled. | | 'csrf_token_name' = The token name | 'csrf_cookie_name' = The cookie name | 'csrf_expire' = The number in seconds the token should expire. | 'csrf_regenerate' = Regenerate token on every submission | 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks */
Now if we need to post some data using AJAX then we may need to do some tricks as it is not a simple server-side form posting we may not have the CSRF token field value to our request. So we can do that in the following way.
Define CSRF field name and value as meta to your application like
<meta name="csrfName" content="<?php echo $this->security->get_csrf_token_name(); ?>"> <meta name="csrfHash" content="<?php echo $this->security->get_csrf_hash(); ?>">
And then in the js file fetch these values and push into the request and then send the request like:
var csrfName = $('meta[name=csrfName]').attr("content"); var csrfHash = $('meta[name=csrfHash]').attr("content"); ajaxCall(); function ajaxCall() { var url = ‘YOUR_REQUEST_URL’; var formData = { [csrfName]: csrfHash, postkey: postvalue } $.ajax({ url: url, type: 'post', data: formData, dataType: 'json', success: function (data) { console.log(data); } }); }
Here we can have a problem. If we have to submit the request again we will get rejection as we have the old CSRF token in our request as the page is in its old state by not getting reloaded. To overcome that we can replace the ajax function with the below:
$.ajax({ url: url, type: 'post', data: formData, dataType: 'json', success: function (data) { console.log(data); csrfName = data.csrfName; csrfHash = data.csrfHash; } });
And our server-side code may look like
function postFun() { $reponse = array( 'csrfName' => $this->security->get_csrf_token_name(), 'csrfHash' => $this->security->get_csrf_hash() ); echo json_encode($reponse); }
Or if CSRF Token is not mandatory for your ajax call you may skip CSRF checking for that particular request by specifying it to the config file.
$config['csrf_exclude_uris'] = array('YOUR_ROUTE');
Over 7 years of experience in web development. Worked on Healthcare, Finance, eCommerce, education, etc application.