Skip to content

Instantly share code, notes, and snippets.

@ericcholis
Forked from cgutierrez/action.php
Created August 7, 2013 11:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericcholis/6173448 to your computer and use it in GitHub Desktop.
Save ericcholis/6173448 to your computer and use it in GitHub Desktop.
<?php
use lithium\action\Dispatcher;
use lithium\storage\Session;
use lithium\security\validation\RequestToken;
use lithium\action\Response;
Dispatcher::applyFilter('run', function($self, $params, $chain) {
$request = $params['request'];
$excludes = array('get', 'head', 'options');
if (!in_array(strtolower($request->method), $excludes)) {
$token = $request->env('HTTP_X_CSRF_TOKEN');
if (!empty($request->data['security']) &&
!empty($request->data['security']['token'])) {
$token = $request->data['security']['token'];
}
if (!RequestToken::check($token)) {
// do any sort of logging here
return new Response(array(
'request' => $request,
'location' => Session::read('csrf_redirect')
));
}
}
// generate a new token for all requests besides ajax requests
if (!$request->is('ajax')) {
RequestToken::get(array('regenerate' => true));
Session::write('csrf_redirect', "/" . ltrim($request->url));
}
return $chain->next($self, $params, $chain);
});
// https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
(function(window) {
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ajaxSend(function(event, xhr, settings) {
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRF-Token", $('meta[name="security.token"]').attr('content'));
}
});
})(window);
<?php
namespace app\extensions\helper;
class Security extends \lithium\template\helper\Security {
public function requestToken(array $options = array()) {
$defaults = array('name' => 'security.token', 'id' => false, 'meta' => false);
$options += $defaults;
$requestToken = $this->_classes['requestToken'];
$value = $requestToken::key();
$name = $options['name'];
$meta = $options['meta'];
unset($options['name'], $options['meta']);
if ($meta === true) {
$attrs = sprintf('name="%s" content="%s"', $name, $value);
return $this->_context->html->head('meta', array('options' => $attrs));
}
return $this->_context->form->hidden($name, compact('value') + $options);
}
}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<?=$this->Security->requestToken(array('meta' => true));?>
</head>
<body>
<form method="post" action="/some/action">
<?=$this->Security->requestToken(); ?>
</form>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment