Welcome Guest, Not a member yet? Register   Sign In
CI best practices for CSRF and inheritable controllers.
#1

[eluser]jonez[/eluser]
Hi I'm rebuilding a site in CI3-dev and in the process I'm fixing some of the mistakes I made learning the framework. What is the best practice for these two situations?

1. CSRF protection. The entire app lives behind a login page so I don't feel it's necessary to enable CSRF globally and go through the pain of updating every AJAX post to pass the token along. I'm using a controller hook to check the session and redirect as necessary.

Is there a built in way to only enable CSRF for a single form? Enabling the option sets it globally, I could manually include the field in the login form and validate it server side?

2. Inheritable controllers. The app uses a base MY_Controller that every controller extends and I have 3 special controllers that need an extra level of inheritance. They go MY_Controller -> PP_Editor -> Content.

Originally I had this structure:
/controllers/PP_Controller.php
/controllers/PP_Editor.php
/controllers/Content.php

Now I have this structure:
/core/MY_Controller.php
/???/PP_Editor.php
/controllers/Content.php

Where in the new directory structure should PP_Editor.php go? This controller's methods should not be directly accessible and the functionality would be a mess if I tried to turn it into a library.

I could put it in the controllers folder and inherit as before, then put a check in the constructor to see if the URL matches the controllers route and redirect. That seems a bit odd and I'm hoping there's a cleaner way to do it?

Thanks!
#2

[eluser]jonez[/eluser]
Found a solution to #2. You can create routes that force error messages (404), so I placed the editor controller in the controller folder and added the following routes:

$route['editor'] = 'error_mess';
$route['editor/(:any)'] = 'error_mess';

Still looking for a way to make #1 work, $this->security->get_csrf_hash() doesn't seem to generate a value unless CSRF is enabled globally.
#3

[eluser]jonez[/eluser]
Found a solution to #1. You can enable/disable config settings at run time using a pre-system hook.

Code:
$hook['pre_system'][] = array(
'function' => 'check_csrf',
'filename' => 'csrf.php',
'filepath' => 'hooks',
);

/hooks/csrf.php:
Code:
<?php

function check_csrf( ) {
if ( stripos( $_SERVER[ 'REQUEST_URI' ], '/login' ) !== false ) {
  $config =& load_class( 'Config', 'core' );
  $config->set_item( 'csrf_protection', true );
}
}

?>

Pass values into view:
Code:
$data = array(
'page_title' => 'Login',
'csrf_name' => $this->security->get_csrf_token_name( ),
'csrf_hash' => $this->security->get_csrf_hash( ),
);

Include fields in view if not using form_open():
Code:
<input name="<?=$csrf_name?>" value="<?=$csrf_hash?>" type="hidden" />




Theme © iAndrew 2016 - Forum software by © MyBB