Implemented $c->allow_ssl.
[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
ffd9355f 7our $VERSION = '0.07';
1763fe29 8
c4744895 9__PACKAGE__->mk_accessors( qw/_require_ssl _allow_ssl _ssl_strip_output/ );
eeefd598 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 {
4585dfb1 22 $c->_ssl_strip_output(1);
eeefd598 23 $c->res->redirect( $redir );
24 }
25 }
26}
27
c4744895 28sub allow_ssl {
29 my $c = shift;
30
31 $c->_allow_ssl(1);
32}
33
eeefd598 34sub finalize {
35 my $c = shift;
36
37 # Do not redirect static files (only works with Static::Simple)
38 if ( $c->isa( "Catalyst::Plugin::Static::Simple" ) ) {
39 return $c->NEXT::finalize(@_) if $c->_static_file;
40 }
41
42 # redirect back to non-SSL mode
43 REDIRECT:
44 {
45 # No redirect if:
46 # we're not in SSL mode
47 last REDIRECT if !$c->req->secure;
48 # it's a POST request
49 last REDIRECT if $c->req->method eq "POST";
50 # we're already required to be in SSL for this request
51 last REDIRECT if $c->_require_ssl;
52 # or the user doesn't want us to redirect
c4744895 53 last REDIRECT if $c->config->{require_ssl}->{remain_in_ssl} || $c->_allow_ssl;
eeefd598 54
55 $c->res->redirect( $c->_redirect_uri('http') );
56 }
57
4585dfb1 58 # do not allow any output to be displayed on the insecure page
59 if ( $c->_ssl_strip_output ) {
cc4f2717 60 $c->res->body( '' );
4585dfb1 61 }
62
eeefd598 63 return $c->NEXT::finalize(@_);
64}
65
66sub setup {
67 my $c = shift;
68
69 $c->NEXT::setup(@_);
70
71 # disable the plugin when running under certain engines which don't
72 # support SSL
cae2ad7f 73 if ( $c->engine =~ /Catalyst::Engine::HTTP/ ) {
eeefd598 74 $c->config->{require_ssl}->{disabled} = 1;
75 $c->log->warn( "RequireSSL: Disabling SSL redirection while running "
76 . "under " . $c->engine );
77 }
78}
79
80sub _redirect_uri {
81 my ( $c, $type ) = @_;
82
83 # XXX: Cat needs a $c->req->host method...
84 # until then, strip off the leading protocol from base
85 if ( !$c->config->{require_ssl}->{$type} ) {
86 my $host = $c->req->base;
87 $host =~ s/^http(s?):\/\///;
88 $c->config->{require_ssl}->{$type} = $host;
89 }
90
91 if ( $c->config->{require_ssl}->{$type} !~ /\/$/xms ) {
92 $c->config->{require_ssl}->{$type} .= '/';
93 }
94
95 my $redir
96 = $type . '://' . $c->config->{require_ssl}->{$type} . $c->req->path;
4585dfb1 97
eeefd598 98 if ( scalar $c->req->param ) {
4585dfb1 99 my @params;
100 foreach my $arg ( sort keys %{ $c->req->params } ) {
101 if ( ref $c->req->params->{$arg} ) {
102 my $list = $c->req->params->{$arg};
103 push @params, map { "$arg=" . $_ } sort @{$list};
104 }
105 else {
106 push @params, "$arg=" . $c->req->params->{$arg};
107 }
108 }
109 $redir .= '?' . join( '&', @params );
51ef6cb3 110 }
111
b0b7bb46 112 if ( $c->config->{require_ssl}->{no_cache} ) {
ffd9355f 113 delete $c->config->{require_ssl}->{$type};
114 }
115
eeefd598 116 return $redir;
117}
118
1191;
120__END__
1763fe29 121
122=head1 NAME
123
124Catalyst::Plugin::RequireSSL - Force SSL mode on select pages
125
126=head1 SYNOPSIS
127
eeefd598 128 # in MyApp.pm
129 use Catalyst;
130 MyApp->setup( qw/RequireSSL/ );
1763fe29 131
132 MyApp->config->{require_ssl} = {
133 https => 'secure.mydomain.com',
134 http => 'www.mydomain.com',
135 remain_in_ssl => 0,
ffd9355f 136 no_cache => 0,
1763fe29 137 };
138
eeefd598 139 # in any controller methods that should be secured
1763fe29 140 $c->require_ssl;
141
142=head1 DESCRIPTION
143
eeefd598 144Use this plugin if you wish to selectively force SSL mode on some of your web
145pages, for example a user login form or shopping cart.
1763fe29 146
eeefd598 147Simply place $c->require_ssl calls in any controller method you wish to be
148secured.
1763fe29 149
eeefd598 150This plugin will automatically disable itself if you are running under the
151standalone HTTP::Daemon Catalyst server. A warning message will be printed to
152the log file whenever an SSL redirect would have occurred.
1763fe29 153
154=head1 WARNINGS
155
eeefd598 156If you utilize different servers or hostnames for non-SSL and SSL requests,
157and you rely on a session cookie to determine redirection (i.e for a login
158page), your cookie must be visible to both servers. For more information, see
159the documentation for the Session plugin you are using.
1763fe29 160
161=head1 CONFIGURATION
162
163Configuration is optional. You may define the following configuration values:
164
165 https => $ssl_host
166
167If your SSL domain name is different from your non-SSL domain, set this value.
168
169 http => $non_ssl_host
170
eeefd598 171If you have set the https value above, you must also set the hostname of your
172non-SSL server.
1763fe29 173
174 remain_in_ssl
175
eeefd598 176If you'd like your users to remain in SSL mode after visiting an SSL-required
177page, you can set this option to 1. By default, this option is disabled and
178users will be redirected back to non-SSL mode as soon as possible.
1763fe29 179
ffd9355f 180 no_cache
11f9b043 181
182If you have a wildcard certificate you will need to set this option if you are
51ef6cb3 183using multiple domains on one instance of Catalyst.
11f9b043 184
eeefd598 185=head1 METHODS
1763fe29 186
eeefd598 187=head2 require_ssl
1763fe29 188
189Call require_ssl in any controller method you wish to be secured.
190
191 $c->require_ssl;
192
eeefd598 193The browser will be redirected to the same path on your SSL server. POST
194requests are never redirected.
1763fe29 195
c4744895 196=head2 allow_ssl
197
198Call allow_ssl in any controller method you wish to access both in SSL and
199non-SSL mode.
200
201 $c->allow_ssl;
202
203The browser will not be redirected, independently of whether the request was
204made to the SSL or non-SSL server.
205
ffd9355f 206=head2 setup
207
208Disables this plugin if running under an engine which does not support SSL.
209
210=head2 finalize
211
212Performs the redirect to SSL url if required.
213
1763fe29 214=head1 KNOWN ISSUES
215
eeefd598 216When viewing an SSL-required page that uses static files served from the
217Static plugin, the static files are redirected to the non-SSL path.
1763fe29 218
eeefd598 219In order to get the correct behaviour where static files are not redirected,
220you should use the Static::Simple plugin or always serve static files
221directly from your web server.
1763fe29 222
223=head1 SEE ALSO
224
eeefd598 225L<Catalyst>, L<Catalyst::Plugin::Static::Simple>
1763fe29 226
227=head1 AUTHOR
228
eeefd598 229Andy Grundman, <andy@hybridized.org>
1763fe29 230
11f9b043 231=head1 CONTRIBUTORS
232
233Simon Elliott <simon@browsing.co.uk> (support for wildcards)
234
1763fe29 235=head1 COPYRIGHT
236
237This program is free software, you can redistribute it and/or modify it under
238the same terms as Perl itself.
239
240=cut