From: Andy Grundman Date: Tue, 6 Sep 2005 02:11:47 +0000 (+0000) Subject: Released RequireSSL 0.03: code cleanup and Static::Simple support X-Git-Tag: v0.03^0 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=eeefd5982dc7052c1e714cc00160b77cfe17d56e;hp=d5e430c2b2ee92606b92e1f031c33910e566be06;p=catagits%2FCatalyst-Plugin-RequireSSL.git Released RequireSSL 0.03: code cleanup and Static::Simple support --- diff --git a/Changes b/Changes index 3662180..c850236 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,10 @@ Revision history for Perl extension Catalyst::Plugin::RequireSSL +0.03 2005-09-05 22:00:00 + - Proper handling for static files in SSL mode when using + Static::Simple. + - Code cleanup per Best Practices. + 0.02 2005-06-23 20:40:00 - fixed README file diff --git a/META.yml b/META.yml index b7a20d3..38dcb58 100644 --- a/META.yml +++ b/META.yml @@ -1,8 +1,14 @@ ---- #YAML:1.0 +--- name: Catalyst-Plugin-RequireSSL -version: 0.01 +version: 0.03 author: - - Andy Grundman, C + - 'Andy Grundman, ' abstract: Force SSL mode on select pages license: perl -generated_by: Module::Build version 0.2604, without YAML.pm +requires: + Catalyst: 5.23 +provides: + Catalyst::Plugin::RequireSSL: + file: lib/Catalyst/Plugin/RequireSSL.pm + version: 0.03 +generated_by: Module::Build version 0.2611 diff --git a/README b/README index 5098a8b..72e8620 100644 --- a/README +++ b/README @@ -2,7 +2,9 @@ NAME Catalyst::Plugin::RequireSSL - Force SSL mode on select pages SYNOPSIS - use Catalyst 'RequireSSL'; + # in MyApp.pm + use Catalyst; + MyApp->setup( qw/RequireSSL/ ); MyApp->config->{require_ssl} = { https => 'secure.mydomain.com', @@ -10,6 +12,7 @@ SYNOPSIS remain_in_ssl => 0, }; + # in any controller methods that should be secured $c->require_ssl; DESCRIPTION @@ -46,42 +49,32 @@ CONFIGURATION remain_in_ssl If you'd like your users to remain in SSL mode after visiting an - SSL-required page, you can set this option to 1. By default, users will - be redirected back to non-SSL mode as soon as possible. + SSL-required page, you can set this option to 1. By default, this option + is disabled and users will be redirected back to non-SSL mode as soon as + possible. - METHODS - require_ssl - Call require_ssl in any controller method you wish to be secured. +METHODS + require_ssl + Call require_ssl in any controller method you wish to be secured. - $c->require_ssl; - - The browser will be redirected to the same path on your SSL server. - POST requests are never redirected. - - finalize (extended) - Redirect back to non-SSL mode if necessary. - - setup - Setup default values. + $c->require_ssl; - _redirect_uri - Generate the redirection URI. + The browser will be redirected to the same path on your SSL server. POST + requests are never redirected. KNOWN ISSUES When viewing an SSL-required page that uses static files served from the - Static plugin, the static files are redirected to the non-SSL path. It - may be possible to work around this by checking the referer protocol, - but currently there is no way to determine if a file being served is - static content. + Static plugin, the static files are redirected to the non-SSL path. - For best results, always serve static files directly from your web - server without using the Static plugin. + In order to get the correct behaviour where static files are not + redirected, you should use the Static::Simple plugin or always serve + static files directly from your web server. SEE ALSO - Catalyst + Catalyst, Catalyst::Plugin::Static::Simple AUTHOR - Andy Grundman, "andy@hybridized.org" + Andy Grundman, COPYRIGHT This program is free software, you can redistribute it and/or modify it diff --git a/lib/Catalyst/Plugin/RequireSSL.pm b/lib/Catalyst/Plugin/RequireSSL.pm index 452cd3f..a03aad5 100644 --- a/lib/Catalyst/Plugin/RequireSSL.pm +++ b/lib/Catalyst/Plugin/RequireSSL.pm @@ -4,9 +4,98 @@ use strict; use base qw/Class::Accessor::Fast/; use NEXT; -our $VERSION = '0.02'; +our $VERSION = '0.03'; -__PACKAGE__->mk_accessors( '_require_ssl' ); +__PACKAGE__->mk_accessors('_require_ssl'); + +sub require_ssl { + my $c = shift; + + $c->_require_ssl(1); + + if ( !$c->req->secure && $c->req->method ne "POST" ) { + my $redir = $c->_redirect_uri('https'); + if ( $c->config->{require_ssl}->{disabled} ) { + $c->log->warn( "RequireSSL: Would have redirected to $redir" ); + } + else { + $c->res->redirect( $redir ); + } + } +} + +sub finalize { + my $c = shift; + + # Do not redirect static files (only works with Static::Simple) + if ( $c->isa( "Catalyst::Plugin::Static::Simple" ) ) { + return $c->NEXT::finalize(@_) if $c->_static_file; + } + + # redirect back to non-SSL mode + REDIRECT: + { + # No redirect if: + # we're not in SSL mode + last REDIRECT if !$c->req->secure; + # it's a POST request + last REDIRECT if $c->req->method eq "POST"; + # we're already required to be in SSL for this request + last REDIRECT if $c->_require_ssl; + # or the user doesn't want us to redirect + last REDIRECT if $c->config->{require_ssl}->{remain_in_ssl}; + + $c->res->redirect( $c->_redirect_uri('http') ); + } + + return $c->NEXT::finalize(@_); +} + +sub setup { + my $c = shift; + + $c->NEXT::setup(@_); + + # disable the plugin when running under certain engines which don't + # support SSL + # XXX: I didn't include Catalyst::Engine::Server here as it may be used as + # a backend in a proxy setup. + if ( $c->engine eq "Catalyst::Engine::HTTP" ) { + $c->config->{require_ssl}->{disabled} = 1; + $c->log->warn( "RequireSSL: Disabling SSL redirection while running " + . "under " . $c->engine ); + } +} + +sub _redirect_uri { + my ( $c, $type ) = @_; + + # XXX: Cat needs a $c->req->host method... + # until then, strip off the leading protocol from base + if ( !$c->config->{require_ssl}->{$type} ) { + my $host = $c->req->base; + $host =~ s/^http(s?):\/\///; + $c->config->{require_ssl}->{$type} = $host; + } + + if ( $c->config->{require_ssl}->{$type} !~ /\/$/xms ) { + $c->config->{require_ssl}->{$type} .= '/'; + } + + my $redir + = $type . '://' . $c->config->{require_ssl}->{$type} . $c->req->path; + + if ( scalar $c->req->param ) { + my @params + = map { "$_=" . $c->req->params->{$_} } sort $c->req->param; + $redir .= "?" . join "&", @params; + } + + return $redir; +} + +1; +__END__ =head1 NAME @@ -14,7 +103,9 @@ Catalyst::Plugin::RequireSSL - Force SSL mode on select pages =head1 SYNOPSIS - use Catalyst 'RequireSSL'; + # in MyApp.pm + use Catalyst; + MyApp->setup( qw/RequireSSL/ ); MyApp->config->{require_ssl} = { https => 'secure.mydomain.com', @@ -22,25 +113,27 @@ Catalyst::Plugin::RequireSSL - Force SSL mode on select pages remain_in_ssl => 0, }; + # in any controller methods that should be secured $c->require_ssl; =head1 DESCRIPTION -Use this plugin if you wish to selectively force SSL mode on some of your web pages, -for example a user login form or shopping cart. +Use this plugin if you wish to selectively force SSL mode on some of your web +pages, for example a user login form or shopping cart. -Simply place $c->require_ssl calls in any controller method you wish to be secured. +Simply place $c->require_ssl calls in any controller method you wish to be +secured. -This plugin will automatically disable itself if you are running under the standalone -HTTP::Daemon Catalyst server. A warning message will be printed to the log file whenever -an SSL redirect would have occurred. +This plugin will automatically disable itself if you are running under the +standalone HTTP::Daemon Catalyst server. A warning message will be printed to +the log file whenever an SSL redirect would have occurred. =head1 WARNINGS -If you utilize different servers or hostnames for non-SSL and SSL requests, and you rely -on a session cookie to determine redirection (i.e for a login page), your cookie must -be visible to both servers. For more information, see the documentation for the Session plugin -you are using. +If you utilize different servers or hostnames for non-SSL and SSL requests, +and you rely on a session cookie to determine redirection (i.e for a login +page), your cookie must be visible to both servers. For more information, see +the documentation for the Session plugin you are using. =head1 CONFIGURATION @@ -52,138 +145,42 @@ If your SSL domain name is different from your non-SSL domain, set this value. http => $non_ssl_host -If you have set the https value above, you must also set the hostname of your non-SSL -server. +If you have set the https value above, you must also set the hostname of your +non-SSL server. remain_in_ssl -If you'd like your users to remain in SSL mode after visiting an SSL-required page, you can -set this option to 1. By default, users will be redirected back to non-SSL mode as soon as -possible. +If you'd like your users to remain in SSL mode after visiting an SSL-required +page, you can set this option to 1. By default, this option is disabled and +users will be redirected back to non-SSL mode as soon as possible. -=head2 METHODS +=head1 METHODS -=over 4 - -=item require_ssl +=head2 require_ssl Call require_ssl in any controller method you wish to be secured. $c->require_ssl; -The browser will be redirected to the same path on your SSL server. POST requests -are never redirected. - -=cut - -sub require_ssl { - my $c = shift; - - $c->_require_ssl( 1 ); - - unless ( $c->req->secure || $c->req->method eq "POST" ) { - if ( $c->config->{require_ssl}->{disabled} ) { - $c->log->warn( "RequireSSL: Would have redirected to " . $c->_redirect_uri( 'https' ) ); - } else { - $c->res->redirect( $c->_redirect_uri( 'https' ) ); - } - } -} - -=item finalize (extended) - -Redirect back to non-SSL mode if necessary. - -=cut - -sub finalize { - my $c = shift; - - # redirect unless: - # we're not in SSL mode, - # it's a POST request, - # we're already required to be in SSL for this request, - # or the user doesn't want us to redirect - unless ( !$c->req->secure - || $c->req->method eq "POST" - || $c->_require_ssl - || $c->config->{require_ssl}->{remain_in_ssl} ) { - $c->res->redirect( $c->_redirect_uri( 'http' ) ); - } - - return $c->NEXT::finalize(@_); -} - -=item setup - -Setup default values. - -=cut - -sub setup { - my $c = shift; - - $c->NEXT::setup(@_); - - # disable the plugin when running under certain engines which don't support SSL - # XXX: I didn't include Catalyst::Engine::Server here as it may be used as a backend - # in a proxy setup. - if ( $c->engine eq "Catalyst::Engine::HTTP" ) { - $c->config->{require_ssl}->{disabled} = 1; - $c->log->warn( "RequireSSL: Disabling SSL redirection while running under " . $c->engine ); - } -} - -=item _redirect_uri - -Generate the redirection URI. - -=cut - -sub _redirect_uri { - my ( $c, $type ) = @_; - - # XXX: Cat needs a $c->req->host method... - # until then, strip off the leading protocol from base - unless ( $c->config->{require_ssl}->{$type} ) { - my $host = $c->req->base; - $host =~ s/^http(s?):\/\///; - $c->config->{require_ssl}->{$type} = $host; - } - - $c->config->{require_ssl}->{$type} .= '/' - unless ( $c->config->{require_ssl}->{$type} =~ /\/$/ ); - - my $redir = $type . '://' . $c->config->{require_ssl}->{$type} . $c->req->path; - if ( scalar keys %{ $c->req->params } ) { - my @params = (); - foreach my $k ( sort keys %{ $c->req->params } ) { - push @params, $k . "=" . $c->req->params->{$k}; - } - $redir .= "?" . join "&", @params; - } - - return $redir; -} - -=back +The browser will be redirected to the same path on your SSL server. POST +requests are never redirected. =head1 KNOWN ISSUES -When viewing an SSL-required page that uses static files served from the Static plugin, the static -files are redirected to the non-SSL path. It may be possible to work around this by checking the -referer protocol, but currently there is no way to determine if a file being served is static content. +When viewing an SSL-required page that uses static files served from the +Static plugin, the static files are redirected to the non-SSL path. -For best results, always serve static files directly from your web server without using the Static -plugin. +In order to get the correct behaviour where static files are not redirected, +you should use the Static::Simple plugin or always serve static files +directly from your web server. =head1 SEE ALSO -L +L, L =head1 AUTHOR -Andy Grundman, C +Andy Grundman, =head1 COPYRIGHT @@ -191,5 +188,3 @@ This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself. =cut - -1;