{ use strict; use warnings; package LoginApp; use parent qw/Plack::Component/; use Plack::Util::Accessor qw( secure check_pass render_login ); use Plack::Response; use Plack::Request; sub call { my($self, $env) = @_; my $login_error; if( $self->secure && $env->{'psgi.url_scheme'} ne 'https' ){ my $res = Plack::Response->new; my $secure_url = 'https://' . $env->{SERVER_NAME} . $env->{PATH_INFO}; $res->redirect( $secure_url ); return $res->finalize; } my $params = Plack::Request->new( $env )->parameters; if( defined $env->{user} ){ return 'Already logged in'; } elsif( $env->{REQUEST_METHOD} eq 'POST' ){ my $user_id; ( $login_error, $user_id ) = $self->check_pass->( $params->get( 'username' ), $params->get( 'password' ) ); if( !$login_error ){ $env->{'psgix.session'}{user_id} = $user_id; $env->{'psgix.session'}{remember} = 1 if $params->get( 'remember' ); my $res = Plack::Response->new; my $redir_to = delete $env->{'psgix.session'}{redir_to}; $redir_to = '/' if URI->new( $redir_to )->path eq $env->{PATH_INFO} || !length( $redir_to ); $res->redirect( $redir_to ); return $res->finalize; } } $env->{'psgix.session'}{redir_to} ||= $env->{HTTP_REFERER}; my $render = $self->render_login || \&login_page; return [ 200, { 'Content-Type' => 'text/html', }, [ $render->( username => $params->get( 'username' ), login_error => $login_error, redir_to => $env->{'psgix.session'}{redir_to}, ) ] ]; } sub login_page { my ( %params ) = @_; my $out = "\n"; if( $params{login_error} ){ $out .= "
$params{login_error}
"; } $out .= $params{username}; $out .= <
After login: $params{redir_to}. END return $out; } 1; } { use strict; use warnings; package LogoutApp; use parent qw/Plack::Component/; sub call { my($self, $env) = @_; if( $env->{REQUEST_METHOD} eq 'POST' ){ delete $env->{'psgix.session'}{user_id}; } return [ 303, { Location => '/' }, [] ]; } 1; } use strict; use warnings; package main; #use LoginApp; #use LogoutApp; use Plack::Builder; sub check_pass { my( $username, $pass ) = @_; if( $username eq $pass ){ return 0, $username; } else{ return 'Wrong username or password'; } } builder { enable 'Session'; mount '/login' => LoginApp->new( check_pass => \&check_pass )->to_app; mount '/logout' => LogoutApp->new()->to_app; mount '/' => sub { my $env = shift; my $page = '' . $env->{PATH_INFO} . '
'; if( $env->{'psgix.session'}{user_id} ){ $page .= 'Hi ' . $env->{'psgix.session'}{user_id} . '
'; } else{ $page .= 'login'; } $page .= ''; return [ 200, { 'Content-Type' => 'text/html', }, [ $page ] ]; } };