Welcome Guest, Not a member yet? Register   Sign In
Setting csrf_regenerate as TRUE
#1

I am using CI3.

When I set $config['csrf_regenerate'] = TRUE;, after the first request, subsequent ajax requests fail.

This is obviously because of the csrf token being regenarated after every request.

In the header.php page, I am using

Quote:<script type="text/javascript" language="javascript">
var csfrData = {};
csfrData['<?php echo $this->security->get_csrf_token_name(); ?>'] = '<?php echo $this->security->get_csrf_hash(); ?>';
 </script>

Then there is a csrfload.js page, where I am using ajaxSetup function to send the token with every request..

Quote:$(function() {
    // Attach csfr data token
    $.ajaxSetup({
       data: csfrData
    });
});

Now how do I change this code to include csrf token generation with every request? Also, setting csrf_regenerate as TRUE may give problem is multiple tabs/windows ?
Reply
#2

Return the new CSRF token in your response and update the CSRF variable in your JavaScript.

Remember to always include the CSRF token no matter the status of execution. Both success and fails should return the new CSRF token.
Reply
#3

Another issue with this setting is you can only ever fire a single AJAX request at a time. Concurrent requests will fail.
Reply
#4

(07-27-2017, 05:52 AM)Martin7483 Wrote: Return the new CSRF token in your response and update the CSRF variable in your JavaScript.

Remember to always include the CSRF token no matter the status of execution. Both success and fails should return the new CSRF token.

Martin, can you please show this with the code i have posted? 

I am not using concurrent requests, one request at a time will do.
Reply
#5

First I'm asuming you are using jQuery Wink

Your AJAX code should have a success and error handler for responses.
The controller/method that is called via the AJAX could respond with JSON output

Code:
$.ajax({
   type: "POST",
   dataType: "json",
   url: 'http://www.somewebsite.com/some-controller/some-method',
   data: theDataYouAreSending,
   success: function(data){
       // This is a success response
       csfrData = {};
       csfrData[data.csrfTokenName] = data.csrfTokenHash;
   },
   error: function(data) {
       // This is a error response
       csfrData = {};
       csfrData[data.csrfTokenName] = data.csrfTokenHash;
   }
});

In the called method you could do this

PHP Code:
$response = array('success'=>TRUE/FALSE);
$response['csrfTokenName'] = $this->security->get_csrf_token_name();
$response['csrfTokenHash'] = $this->security->get_csrf_hash();

header('Content-Type: application/json');
echo 
json_encode($response);
exit; 

The data argument in function(data) is an object containing what ever you added to the output
Reply
#6

Thanks Martin. I am using jquery.

I am giving detailed code here:

Quote:$('#project_id').change(function() {

        var project_id=$("#project_id").val();
        var domain=$("#domain").val();

        $.ajax({
                type: "POST",
                url: domain + "index.php/project/get_department",
                data: {project_id: project_id},
                dataType: 'json',
                success: 
            function(j){              
 
              if(j.length >= 2) {
                var options = '';
                for (var i = 0; i < j.length; i++) {
                        options += '<option value="' + j[i].id + '">' + j[i].name + '</option>';
                }
                $("#department_id").html(options);
                $('#department_id option:first').attr('selected', 'selected');
              }
              else if (j.length == 1){
         
               options += '<option value="' + j[0].id + '">' + '------------------------------------' + '</option>';
                $("#department_id").html(options);
                $('#department_id option:first').attr('selected', 'selected');
              }
              else{
                $("#department_id").val(j[1].id);
              }
              
            }
          });  
  });  

The get_department function is below:

Quote:public function get_department()
    {

        $project_id = $this->input->post('project_id');      
        if(is_numeric($project_id) && $project_id > 0 && $project_id == round($project_id, 0)){

        $sql = "SELECT department.id, department.name FROM project, department,project_dept
        WHERE project.id= ? and project.id= project_dept.project_id and department.id= project_dept.department_id order by            department.name";
        $query = $this->db->query($sql, array($project_id));
        $loop = html_escape($query->result_array());
    
        $r[0] = "----- Select Departments -----";
        foreach ($loop as $row)
        $r[$row['id']] = $row['name'];
 
        $dept = $r;

        $json = '['; 
        $json_names = array();
        foreach ($dept as $id => $name) {
          $json_names[] = '{"id": "'.$id.'", "name": "'.$name.'"}';
        }
        
        $json .= implode(',', $json_names); 
        $json .= ']'; 
        echo $json;     
}
    else
exit();
    }

Now how do I incorporate your json code with this code ?
Reply
#7

(This post was last modified: 07-28-2017, 01:59 AM by Martin7483.)

First
Why don't you use the PHP function json_encode?
Your two foreach loops can be done in 1 foreach and there is no need to create a json string in that manner.

Second
I'm not going to write the code for you.
You have all the pieces of the puzzle, and it shouldn't be that hard to figure out.
Looking at your code you should be able to do it

But to help you out a bit

PHP Code:
$departments = array();
foreach (
$loop as $row)
{
 
   $departments[] = array('id'=>$row['id'],'name'=>$row['name']);
}
 
$response['departments'] = $departments
Reply
#8

Thanks Martin for your help and giving some much needed confidence  Wink

But to be honest, I am not very good with this json/jquery stuff. Thats why I had to stitch up that weird json string. Now I have done this far:
Quote:foreach ($loop as $row)
{
$departments[] = array('id'=>$row['id'],'name'=>$row['name']);
}

$response
['departments'] = $departments
$response['csrfTokenName'] = $this->security->get_csrf_token_name();
$response['csrfTokenHash'] = $this->security->get_csrf_hash();

echo json_encode($response);

Then in ajax part:

Quote:$('#project_id').change(function() {

        var project_id=$("#project_id").val();
        var domain=$("#domain").val();

        $.ajax({
                type: "POST",
                url: domain + "index.php/project/get_department",
                data: {project_id: project_id},
                dataType: 'json',
                success: 
            function(j){                
                              csfrData = {};
                              csfrData[j.csrfTokenName] = j.csrfTokenHash;
 
              if(j.departments.length >=2) {
                var options = '';
                for (var i = 0; i < (j.departments.length-1); i++) {
                        options += '<option value="' + j.departments[i].id + '">' + j.departments[i].name + '</option>';
                }
                $("#department_id").html(options);
                $('#department_id option:first').attr('selected', 'selected');
              }
              else if (j.departments.length == 1){
         
               options += '<option value="' + j.departments[0].id + '">' + '------------------------------------' + '</option>';
                $("#department_id").html(options);
                $('#department_id option:first').attr('selected', 'selected');
              }
              else{
                $("#department_id").val(j.departments[1].id);
              }
              
            }
          });  
  }); 
Now the next combobox doesnt get populated:
Quote:$('#department_id').change(function() {

         var department_id=$("#department_id").val();
         var domain=$("#domain").val();  
    
        $.ajax({
                type: "POST",
                url: domain + "index.php/project/get_scheme",
                data: {department_id: department_id},
                dataType: 'json',
                success: 

When I checked the console in developer tools(chrome), the following msg comes:
Failed to load resource: the server responded with a status of 403 (Forbidden)                   get_scheme
Maybe the ajaxSetup function in csrf.js file is not sending the updated token:
$(function() {
    // Attach csfr data token
    $.ajaxSetup({
       data: csfrData
    });
});
Kindly guide.
Reply
#9

The csfrData is not being updated. Plese help in resolving this issue.
Reply
#10

First I spotted this on the jQuery website regarding ajaxSetup
Set default values for future Ajax requests. Its use is not recommended.

If I understand correctly, the use of this function will effect all following AJAX calls.
Once it has been declared the values are not updated.
So yes, I think this is the problem and you should not use it.

Create your own set and get functions for the CSRF

PHP Code:
<script type="text/javascript" language="javascript">
 
   var csfrData// Declare globally
 
   csfrTokenName '<?php echo $this->security->get_csrf_token_name(); ?>';
 
   csfrHash '<?php echo $this->security->get_csrf_hash(); ?>';

 
   setCSRF(csfrTokenNamecsfrHash);

 
   function setCSRF(namevalue) {
 
       csfrData = {}; // Reset csrfData to an empty array
 
       csfrData[name] = value;
 
   }

 
   function getCSRF() {
 
       return csrfData;
 
   }
</
script

And from the AJAX call you of course call the setCSRF function with the returned CSRF to update
Reply




Theme © iAndrew 2016 - Forum software by © MyBB