AJAX with CSRF Protection in Codeigniter 2.0
Update: With the official CI 2.0 (Reactor) release, the names of the CSRF token cookie, and the hidden form input element, have been changed from ci_csrf_token to csrf_token_name . This post has been updated to reflect that change.
Codeigniter 2.0 adds an important security feature to prevent CSRF (Cross Site Request Forgery) attacks. Even better, the feature is automatically added to your forms, assuming that
you've enabled it in config.php, and you're using the form_open() function from the Form Helper
Bastian Heist wrote a great post about CSRF, and Codeigniter's handling of it, a couple of weeks ago. I'll provide a very brief overview of the handling here, but I encourage you to go read Bastian's post.
The CSRF detection and protection occurs behind the scenes, in the course of normal form processing. An input type=hidden element is automatically added to the form by the form_open() function. When the form is submitted, the Security class looks for this element and attempts to match its value against a cookie bearing the same name. If they don't match, the form will be rejected.
Since this happens behind the scenes, your normal form processing will not require any remediation when you upgrade from CI 1.7.x to CI 2.0.
Note that I said "normal form processing". I came upon this knowledge when I converted a dev site from 1.7.2 to 2.0, only to find that all of my AJAX functions were returning 500 Internal Server Errors.
I hadn't a clue at the time what was causing this, and initially assumed that it was an issue with my hosting provider. Since it was a dev site, and I was entertaining a colleague, I ignored the issue until he left.
Then I noticed that the response header was a CI style error message - "An Error Was Encountered. The action you have requested is not allowed." So I posted a question to the CI forum and called it a night.
The next morning I found a reply directing me toward CSRF protection being the cause the issue and I started my research, ultimately ending up with Bastian's post.
Unfortunately, though, I didn't find much about remediating AJAX requests, so I was on my own. I came up with two solutions.
Method 1 - Interrogate the Hidden csrf_token_name Input Element
If you are only using AJAX in forms (autocompletes, cascading selects, checking the uniqueness of fields, etc), you can interrogate the csrf_token_name hidden input element and include that in your AJAX request. In jQuery, this might look like:
// get the token value var cct = $("input[name=csrf_token_name]").val(); // add the token to the load request $(".addform #state, .searchform #state").change(function () { var p = $("#state option:selected").val(); if (p > 0) { $('#county').load('/ajax/counties/get', {'state_id': p, 'csrf_token_name': cct}, function (data) {this.value = data;}); } });
This worked perfectly, from within forms. But I use AJAX for much more than just forms. For example, following the principle of progressive enhancement, I use AJAX to intercept several classes of anchor tags and perform their work in place, rather than generating a new page. There is no form element on the pages that I'm intercepting these anchor tags from, so Method 1 is not available to me in these cases.
Method 2 - Interrogating the csrf_token_name Cookie
Since there is no form element to interrogate, I have to get the token from the cookie.
This is a little more involved, since jQuery doesn't natively provide cookie access. So, first, I had to download and install a cookie plugin from the jQuery site.
Then, getting the cookie was as easy as calling the function in the plugin var cct = $.cookie('csrf_token_name'); And including it in AJAX requests worked the same as in method 1
$(".createlink").click(function(){ var itag = ''; var p = $(this).attr('href'); $(this).load('/ajax/link/add', {'uri': p, 'csrf_token_name': cct}); $(this).empty().replaceWith(itag); return false; });
If you're using another library instead of jQuery, the specifics of the remediation will obviously differ. But the principles remain the same:
You must include the csrf_token_name value as a parameter in your AJAX request You can get that token from the hidden element if you're using a form. Otherwise, you will have to get it from the cookie
So, cookie interrogation (method 2) is how I ultimately remediated all of my AJAX requests after upgrading to CI 2.0. As of now, it seems to be working flawlessly.
If you found another solution, please add it in the comments! http://aymsystems.com/ajax-csrf-protection-codeigniter-20#comment-340
from http://chess72.tistory.com/134 by ccl(A) rewrite - 2020-03-06 08:54:40
댓글
댓글 쓰기