Amon2-Plugin-Web-CSRFDefender

 view release on metacpan or  search on metacpan

t/014_csrf_defender_post_only.t  view on Meta::CPAN

    sub load_config { +{} }

    __PACKAGE__->load_plugins(
        'Web::CSRFDefender',
        { post_only => 1 }
    );

    get '/form' => sub {
        my $c = shift;
        $c->render('form.tt');
    };
    get '/form_get' => sub {
        my $c = shift;
        $c->render('form_get.tt');
    };
    get '/form_no_method' => sub {
        my $c = shift;
        $c->render('form_no_method.tt');
    };
    get '/form_multi' => sub {
        my $c = shift;
        $c->render('form_multi.tt');
    };
    get '/get-do' => sub {
        my $c = shift;
        $COMMIT++;
        $c->redirect('/finished');
    };
    post '/do' => sub {
        my $c = shift;
        $COMMIT++;
        $c->redirect('/finished');
    };
    get '/finished' => sub {
        Plack::Response->new( 200, [], ['Finished'] );
    };
}

my $app = builder {
    enable 'Session';
    MyApp::Web->to_app();
};

subtest 'post method' => sub {
    local $COMMIT = 0;
    my $mech = Test::WWW::Mechanize::PSGI->new( app => $app, );
    $mech->get_ok('http://localhost/form');
    $mech->content_like(
        qr[<input type="hidden" name="csrf_token" value="[a-zA-Z0-9_-]{40}" />]);
    $mech->submit_form( form_number => 1, fields => { body => 'yay' } );
    is $mech->base, 'http://localhost/finished';
    is $COMMIT, 1;
};

subtest 'deny' => sub {
    local $COMMIT = 0;
    test_psgi
        app => $app,
        client => sub {
            my $cb = shift;
            my $res = $cb->(HTTP::Request->new(POST => 'http://localhost/do'));
            is $res->code, '403';
            is $COMMIT, 0;
        };
};

subtest 'get method' => sub {
    local $COMMIT = 0;
    my $mech = Test::WWW::Mechanize::PSGI->new( app => $app, );
    $mech->get_ok('http://localhost/form_get');
    $mech->content_unlike(
        qr[<input type="hidden" name="csrf_token" value="[a-zA-Z0-9_-]{40}" />]);
    $mech->submit_form( form_number => 1, fields => { body => 'yay' } );
    is $mech->base, 'http://localhost/finished';
    is $COMMIT, 1;
};

subtest 'no method' => sub {
    local $COMMIT = 0;
    my $mech = Test::WWW::Mechanize::PSGI->new( app => $app, );
    $mech->get_ok('http://localhost/form_no_method');
    $mech->content_unlike(
        qr[<input type="hidden" name="csrf_token" value="[a-zA-Z0-9_-]{40}" />]);
    $mech->submit_form( form_number => 1, fields => { body => 'yay' } );
    is $mech->base, 'http://localhost/finished';
    is $COMMIT, 1;
};

subtest 'multi form' => sub {
    my $mech = Test::WWW::Mechanize::PSGI->new( app => $app, );
    $mech->get_ok('http://localhost/form_multi');
    $mech->content_like(
        qr[<form action="/do" method="post" id="f1">\n<input type="hidden" name="csrf_token" value="[a-zA-Z0-9_-]{40}" />]m);
    $mech->content_like(
        qr[<form action="/do" method='POST' id="f2">\n<input type="hidden" name="csrf_token" value="[a-zA-Z0-9_-]{40}" />]m);
    $mech->content_like(
        qr[<form action="/do" method=POST id="f3">\n<input type="hidden" name="csrf_token" value="[a-zA-Z0-9_-]{40}" />]m);

    $mech->content_unlike(
        qr[<form action="/do" id="f4">\n<input type="hidden" name="csrf_token" value="[a-zA-Z0-9_-]{40}" />]m);
};

done_testing;

package MyApp::Web;
__DATA__

@@ form.tt
<!doctype html>
<html>
<form method="post" action="/do">
    <input type="text" name="body" />
    <input type="submit" name="post" />
</form>
</html>

@@ form_get.tt
<!doctype html>
<html>
<form action="/get-do" method="get">
    <input type="text" name="body" />



( run in 0.574 second using v1.01-cache-2.11-cpan-2398b32b56e )