package SessionTest; # for production as lighttpd proxy: # start_server --path /tmp/sessiontest.sock -- plackup -s Starlet/Gazelle # -E development -a bin/app.psgi # for development: # plackup bin/app.psgi -r -p 3000 -s Twiggy [Starman --worker=3] # works with -s Starman --workers=1, but not if workers >1 because session is # destroyed between requests, possibly after a set time (~1 sec) because rapid # form resubmission keeps csrf_token key in session, otherwise it's gone # see also sessiontest.pl for stand-alone script to illustrate use Dancer2; use Data::Printer; use Local::Dancer2::CSRF; use Dancer2::Plugin::Deferred; our $VERSION = '0.1'; set auto_page => 1; hook before => sub { # p config(); if ( request->is_post() ) { debug 'request is post'; my $session = session; # p $session; my $csrf_token = body_parameters->get('csrf_token'); debug "csrf_token:$csrf_token"; unless ( $csrf_token && check_csrf_token($csrf_token) ) { debug 'invalid CSRF token, redirecting'; deferred error => 'invalid CSRF token, redirecting'; var error => 'invalid CSRF token'; redirect '/'; } } }; hook before_template_render => sub { # does not need session, vars, params, request or settings (automatic) my $tokens = shift; my %uri = map { $_ => uri_for('/' . $_) } qw(); $tokens->{uri_for} = \%uri; $tokens->{get_csrf_token} = get_csrf_token(); # $tokens->{app_config} = config; }; # original '/': get '/index' => sub { template 'index', {}, { layout => 'dancer' } }; # forward GET '/' to same url as POST so CSRF token check passes: get '/' => sub { forward '/sessiontest' }; # handled by auto_page() post '/sessiontest' => sub { deferred success => 'valid CSRF token'; debug 'valid CSRF token'; template 'sessiontest'; }; true;