Amon2-Plugin-Web-CSRFDefender
view release on metacpan or search on metacpan
This plugin denies CSRF request.
Do not use this with [HTTP::Session2](https://metacpan.org/pod/HTTP::Session2). Because [HTTP::Session2](https://metacpan.org/pod/HTTP::Session2) has XSRF token management function by itself.
# METHODS
- $c->get\_csrf\_defender\_token()
Get a CSRF defender token. This method is useful to add token for AJAX request.
- $c->validate\_csrf()
You can validate CSRF token manually.
# PARAMETERS
- no\_validate\_hook
Do not run validation automatically.
- no\_html\_filter
Disable HTML rewriting filter. By default, CSRFDefender inserts XSRF token for each form element.
It's very useful but it hits performance issue if your site is very high traffic.
- csrf\_token\_generator
lib/Amon2/Plugin/Web/CSRFDefender.pm view on Meta::CPAN
unless ($conf->{no_html_filter}) {
$c->add_trigger(
HTML_FILTER => sub {
my ($self, $html) = @_;
$html =~ s!($form_regexp)!qq{$1\n<input type="hidden" name="csrf_token" value="}.$self->get_csrf_defender_token().qq{" />}!ge;
return $html;
},
);
}
unless ($conf->{no_validate_hook}) {
$c->add_trigger(
BEFORE_DISPATCH => sub {
my $self = shift;
if (not $self->validate_csrf()) {
return $self->create_response(
403,
[
'Content-Type' => 'text/html',
'Content-Length' => length($ERROR_HTML)
],
$ERROR_HTML
);
} else {
return;
lib/Amon2/Plugin/Web/CSRFDefender.pm view on Meta::CPAN
Amon2::Util::add_method($c, 'get_csrf_defender_token', sub {
my $self = shift;
if (my $token = $self->session->get('csrf_token')) {
$token;
} else {
my $token = $csrf_token_generator->($self);
$self->session->set('csrf_token' => $token);
$token;
}
});
Amon2::Util::add_method($c, 'validate_csrf', \&validate_csrf);
}
sub validate_csrf {
my $self = shift;
if ( $self->req->method eq 'POST' ) {
my $r_token = $self->req->param('csrf_token') || $self->req->header('x-csrf-token');
my $session_token = $self->session->get('csrf_token');
if ( !$r_token || !$session_token || ( $r_token ne $session_token ) ) {
return 0; # bad
}
}
return 1; # good
lib/Amon2/Plugin/Web/CSRFDefender.pm view on Meta::CPAN
Do not use this with L<HTTP::Session2>. Because L<HTTP::Session2> has XSRF token management function by itself.
=head1 METHODS
=over 4
=item $c->get_csrf_defender_token()
Get a CSRF defender token. This method is useful to add token for AJAX request.
=item $c->validate_csrf()
You can validate CSRF token manually.
=back
=head1 PARAMETERS
=over 4
=item no_validate_hook
Do not run validation automatically.
=item no_html_filter
Disable HTML rewriting filter. By default, CSRFDefender inserts XSRF token for each form element.
It's very useful but it hits performance issue if your site is very high traffic.
=item csrf_token_generator
t/011_csrf_defender_manual.t view on Meta::CPAN
our $COMMIT;
{
package MyApp::Web;
use Amon2::Lite;
sub load_config { +{} }
__PACKAGE__->load_plugins(
'Web::CSRFDefender', {no_validate_hook => 1}
);
get '/form' => sub {
my $c = shift;
$c->render('form.tt');
};
post '/do' => sub {
my $c = shift;
$COMMIT++;
$c->redirect('/finished');
};
post '/do2' => sub {
my $c = shift;
if ($c->validate_csrf) {
$c->create_response(200, [], ['valid token']);
} else {
$c->create_response(403, [], ['denied']);
}
};
get '/finished' => sub {
Plack::Response->new(200, [], ['Finished']);
};
get '/get_csrf_defender_token' => sub {
my $c = shift;
t/011_csrf_defender_manual.t view on Meta::CPAN
test_psgi
app => $app,
client => sub {
my $cb = shift;
my $res = $cb->(HTTP::Request->new(POST => 'http://localhost/do'));
is $res->code, '302';
is $COMMIT, 1;
};
};
subtest 'but you can validate manually' => sub {
local $COMMIT = 0;
test_psgi
app => $app,
client => sub {
my $cb = shift;
my $res = $cb->(HTTP::Request->new(POST => 'http://localhost/do2'));
is $res->code, '403';
is $COMMIT, 0;
};
};
( run in 0.543 second using v1.01-cache-2.11-cpan-a5abf4f5562 )