Released RequireSSL 0.03: code cleanup and Static::Simple support
[catagits/Catalyst-Plugin-RequireSSL.git] / lib / Catalyst / Plugin / RequireSSL.pm
CommitLineData
1763fe29 1package Catalyst::Plugin::RequireSSL;
2
3use strict;
4use base qw/Class::Accessor::Fast/;
5use NEXT;
6
eeefd598 7our $VERSION = '0.03';
1763fe29 8
eeefd598 9__PACKAGE__->mk_accessors('_require_ssl');
10
11sub require_ssl {
12 my $c = shift;
13
14 $c->_require_ssl(1);
15
16 if ( !$c->req->secure && $c->req->method ne "POST" ) {
17 my $redir = $c->_redirect_uri('https');
18 if ( $c->config->{require_ssl}->{disabled} ) {
19 $c->log->warn( "RequireSSL: Would have redirected to $redir" );
20 }
21 else {
22 $c->res->redirect( $redir );
23 }
24 }
25}
26
27sub finalize {
28 my $c = shift;
29
30 # Do not redirect static files (only works with Static::Simple)
31 if ( $c->isa( "Catalyst::Plugin::Static::Simple" ) ) {
32 return $c->NEXT::finalize(@_) if $c->_static_file;
33 }
34
35 # redirect back to non-SSL mode
36 REDIRECT:
37 {
38 # No redirect if:
39 # we're not in SSL mode
40 last REDIRECT if !$c->req->secure;
41 # it's a POST request
42 last REDIRECT if $c->req->method eq "POST";
43 # we're already required to be in SSL for this request
44 last REDIRECT if $c->_require_ssl;
45 # or the user doesn't want us to redirect
46 last REDIRECT if $c->config->{require_ssl}->{remain_in_ssl};
47
48 $c->res->redirect( $c->_redirect_uri('http') );
49 }
50
51 return $c->NEXT::finalize(@_);
52}
53
54sub setup {
55 my $c = shift;
56
57 $c->NEXT::setup(@_);
58
59 # disable the plugin when running under certain engines which don't
60 # support SSL
61 # XXX: I didn't include Catalyst::Engine::Server here as it may be used as
62 # a backend in a proxy setup.
63 if ( $c->engine eq "Catalyst::Engine::HTTP" ) {
64 $c->config->{require_ssl}->{disabled} = 1;
65 $c->log->warn( "RequireSSL: Disabling SSL redirection while running "
66 . "under " . $c->engine );
67 }
68}
69
70sub _redirect_uri {
71 my ( $c, $type ) = @_;
72
73 # XXX: Cat needs a $c->req->host method...
74 # until then, strip off the leading protocol from base
75 if ( !$c->config->{require_ssl}->{$type} ) {
76 my $host = $c->req->base;
77 $host =~ s/^http(s?):\/\///;
78 $c->config->{require_ssl}->{$type} = $host;
79 }
80
81 if ( $c->config->{require_ssl}->{$type} !~ /\/$/xms ) {
82 $c->config->{require_ssl}->{$type} .= '/';
83 }
84
85 my $redir
86 = $type . '://' . $c->config->{require_ssl}->{$type} . $c->req->path;
87
88 if ( scalar $c->req->param ) {
89 my @params
90 = map { "$_=" . $c->req->params->{$_} } sort $c->req->param;
91 $redir .= "?" . join "&", @params;
92 }
93
94 return $redir;
95}
96
971;
98__END__
1763fe29 99
100=head1 NAME
101
102Catalyst::Plugin::RequireSSL - Force SSL mode on select pages
103
104=head1 SYNOPSIS
105
eeefd598 106 # in MyApp.pm
107 use Catalyst;
108 MyApp->setup( qw/RequireSSL/ );
1763fe29 109
110 MyApp->config->{require_ssl} = {
111 https => 'secure.mydomain.com',
112 http => 'www.mydomain.com',
113 remain_in_ssl => 0,
114 };
115
eeefd598 116 # in any controller methods that should be secured
1763fe29 117 $c->require_ssl;
118
119=head1 DESCRIPTION
120
eeefd598 121Use this plugin if you wish to selectively force SSL mode on some of your web
122pages, for example a user login form or shopping cart.
1763fe29 123
eeefd598 124Simply place $c->require_ssl calls in any controller method you wish to be
125secured.
1763fe29 126
eeefd598 127This plugin will automatically disable itself if you are running under the
128standalone HTTP::Daemon Catalyst server. A warning message will be printed to
129the log file whenever an SSL redirect would have occurred.
1763fe29 130
131=head1 WARNINGS
132
eeefd598 133If you utilize different servers or hostnames for non-SSL and SSL requests,
134and you rely on a session cookie to determine redirection (i.e for a login
135page), your cookie must be visible to both servers. For more information, see
136the documentation for the Session plugin you are using.
1763fe29 137
138=head1 CONFIGURATION
139
140Configuration is optional. You may define the following configuration values:
141
142 https => $ssl_host
143
144If your SSL domain name is different from your non-SSL domain, set this value.
145
146 http => $non_ssl_host
147
eeefd598 148If you have set the https value above, you must also set the hostname of your
149non-SSL server.
1763fe29 150
151 remain_in_ssl
152
eeefd598 153If you'd like your users to remain in SSL mode after visiting an SSL-required
154page, you can set this option to 1. By default, this option is disabled and
155users will be redirected back to non-SSL mode as soon as possible.
1763fe29 156
eeefd598 157=head1 METHODS
1763fe29 158
eeefd598 159=head2 require_ssl
1763fe29 160
161Call require_ssl in any controller method you wish to be secured.
162
163 $c->require_ssl;
164
eeefd598 165The browser will be redirected to the same path on your SSL server. POST
166requests are never redirected.
1763fe29 167
168=head1 KNOWN ISSUES
169
eeefd598 170When viewing an SSL-required page that uses static files served from the
171Static plugin, the static files are redirected to the non-SSL path.
1763fe29 172
eeefd598 173In order to get the correct behaviour where static files are not redirected,
174you should use the Static::Simple plugin or always serve static files
175directly from your web server.
1763fe29 176
177=head1 SEE ALSO
178
eeefd598 179L<Catalyst>, L<Catalyst::Plugin::Static::Simple>
1763fe29 180
181=head1 AUTHOR
182
eeefd598 183Andy Grundman, <andy@hybridized.org>
1763fe29 184
185=head1 COPYRIGHT
186
187This program is free software, you can redistribute it and/or modify it under
188the same terms as Perl itself.
189
190=cut