| Catalyst-Controller-HTML-FormFu documentation | Contained in the Catalyst-Controller-HTML-FormFu distribution. |
HTML::FormFu::Element::RequestToken - Hidden text field which contains a unique token
my $e = $form->element( { type => 'Token' } );
my $p = $form->element( { plugin => 'Token' } );
This field can prevent CSRF attacks. It contains a random token. After submission the token is checked with the token which is stored in the session of the current user. See "request_token_enable" in Catalyst::Controller::HTML::FormFu for a convenient way how to use it.
Value of the stash key for the Catalyst context object ($c).
Defaults to context.
Time to life for a token in seconds. Defaults to 3600.
Session key which is used to store the tokens. Defaults to __token.
Limit the number of tokens which are kept in the session. Defaults to 20.
Defaults to HTML::FormFu::Constraint::RequestToken and HTML::FormFu::Constraint::Required.
Set the error message.
This method looks in the session for expired tokens and removes them.
Generates a new token and stores it in the stash.
Checks whether a given token is already in the session. Returns 1 if it exists, 0 otherwise.
Catalyst::Controller::HTML::FormFu, HTML::FormFu::Plugin::RequestToken, HTML::FormFu::Constraint::RequestToken
Moritz Onken, onken@houseofdesign.de
This library is free software, you can redistribute it and/or modify it under the same terms as Perl itself.
| Catalyst-Controller-HTML-FormFu documentation | Contained in the Catalyst-Controller-HTML-FormFu distribution. |
package HTML::FormFu::Element::RequestToken; use Moose; use MooseX::ChainedAccessors; extends 'HTML::FormFu::Element::Text'; use HTML::FormFu::Util qw( process_attrs ); use Carp qw( croak ); has expiration_time => ( is => 'rw', traits => ['Chained'], default => 3600 ); has session_key => ( is => 'rw', traits => ['Chained'], default => '__token' ); has context => ( is => 'rw', traits => ['Chained'], default => 'context' ); has limit => ( is => 'rw', traits => ['Chained'], default => 20 ); has message => ( is => 'rw', traits => ['Chained'], default => 'Form submission failed. Please try again.' ); after BUILD => sub { my $self = shift; $self->name('_token'); $self->constraints([qw(RequestToken Required)]); $self->field_type('hidden'); }; sub process_value { my ($self, $value) = @_; return $self->verify_token($value) ? $value : $self->value($self->get_token)->value; } sub verify_token { my ($self, $token) = @_; return undef unless($token); my $form = $self->form; croak "verify_token() can only be called if form has been submitted" if !$form->submitted; my $field_name = $self->name; my $c = $self->form->stash->{ $self->context }; for ( @{ $c->session->{ $self->session_key } || [] } ) { return 1 if ( $_->[0] eq $token ); } return undef; } sub expire_token { my ($self) = @_; my $c = $self->form->stash->{ $self->context }; my @token; for ( @{ $c->session->{ $self->session_key } || [] } ) { push( @token, $_ ) if ( $_->[1] > time ); } @token = splice(@token, -$self->limit, $self->limit) if(@token > $self->limit); $c->session->{ $self->session_key } = \@token; } sub get_token { my ($self) = @_; my $token; my $c = $self->form->stash->{ $self->context }; my @chars = ( 'a' .. 'z', 0 .. 9 ); $token .= $chars[ int( rand() * 36 ) ] for ( 0 .. 15 ); $c->session->{ $self->session_key } ||= []; push @{ $c->session->{ $self->session_key } }, [ $token, time + $self->expiration_time ]; $self->expire_token; return $token; } 1; __END__