Commit | Line | Data |
1763fe29 |
1 | package Catalyst::Plugin::RequireSSL; |
2 | |
3 | use strict; |
4 | use base qw/Class::Accessor::Fast/; |
5 | use NEXT; |
6 | |
ffd9355f |
7 | our $VERSION = '0.07'; |
1763fe29 |
8 | |
c4744895 |
9 | __PACKAGE__->mk_accessors( qw/_require_ssl _allow_ssl _ssl_strip_output/ ); |
eeefd598 |
10 | |
11 | sub 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 |
28 | sub allow_ssl { |
29 | my $c = shift; |
30 | |
31 | $c->_allow_ssl(1); |
32 | } |
33 | |
eeefd598 |
34 | sub 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 | |
66 | sub 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 | |
80 | sub _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 | |
119 | 1; |
120 | __END__ |
1763fe29 |
121 | |
122 | =head1 NAME |
123 | |
124 | Catalyst::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 |
144 | Use this plugin if you wish to selectively force SSL mode on some of your web |
145 | pages, for example a user login form or shopping cart. |
1763fe29 |
146 | |
eeefd598 |
147 | Simply place $c->require_ssl calls in any controller method you wish to be |
148 | secured. |
1763fe29 |
149 | |
eeefd598 |
150 | This plugin will automatically disable itself if you are running under the |
151 | standalone HTTP::Daemon Catalyst server. A warning message will be printed to |
152 | the log file whenever an SSL redirect would have occurred. |
1763fe29 |
153 | |
154 | =head1 WARNINGS |
155 | |
eeefd598 |
156 | If you utilize different servers or hostnames for non-SSL and SSL requests, |
157 | and you rely on a session cookie to determine redirection (i.e for a login |
158 | page), your cookie must be visible to both servers. For more information, see |
159 | the documentation for the Session plugin you are using. |
1763fe29 |
160 | |
161 | =head1 CONFIGURATION |
162 | |
163 | Configuration is optional. You may define the following configuration values: |
164 | |
165 | https => $ssl_host |
166 | |
167 | If your SSL domain name is different from your non-SSL domain, set this value. |
168 | |
169 | http => $non_ssl_host |
170 | |
eeefd598 |
171 | If you have set the https value above, you must also set the hostname of your |
172 | non-SSL server. |
1763fe29 |
173 | |
174 | remain_in_ssl |
175 | |
eeefd598 |
176 | If you'd like your users to remain in SSL mode after visiting an SSL-required |
177 | page, you can set this option to 1. By default, this option is disabled and |
178 | users will be redirected back to non-SSL mode as soon as possible. |
1763fe29 |
179 | |
ffd9355f |
180 | no_cache |
11f9b043 |
181 | |
182 | If you have a wildcard certificate you will need to set this option if you are |
51ef6cb3 |
183 | using multiple domains on one instance of Catalyst. |
11f9b043 |
184 | |
eeefd598 |
185 | =head1 METHODS |
1763fe29 |
186 | |
eeefd598 |
187 | =head2 require_ssl |
1763fe29 |
188 | |
189 | Call require_ssl in any controller method you wish to be secured. |
190 | |
191 | $c->require_ssl; |
192 | |
eeefd598 |
193 | The browser will be redirected to the same path on your SSL server. POST |
194 | requests are never redirected. |
1763fe29 |
195 | |
c4744895 |
196 | =head2 allow_ssl |
197 | |
198 | Call allow_ssl in any controller method you wish to access both in SSL and |
199 | non-SSL mode. |
200 | |
201 | $c->allow_ssl; |
202 | |
203 | The browser will not be redirected, independently of whether the request was |
204 | made to the SSL or non-SSL server. |
205 | |
ffd9355f |
206 | =head2 setup |
207 | |
208 | Disables this plugin if running under an engine which does not support SSL. |
209 | |
210 | =head2 finalize |
211 | |
212 | Performs the redirect to SSL url if required. |
213 | |
1763fe29 |
214 | =head1 KNOWN ISSUES |
215 | |
eeefd598 |
216 | When viewing an SSL-required page that uses static files served from the |
217 | Static plugin, the static files are redirected to the non-SSL path. |
1763fe29 |
218 | |
eeefd598 |
219 | In order to get the correct behaviour where static files are not redirected, |
220 | you should use the Static::Simple plugin or always serve static files |
221 | directly from your web server. |
1763fe29 |
222 | |
223 | =head1 SEE ALSO |
224 | |
eeefd598 |
225 | L<Catalyst>, L<Catalyst::Plugin::Static::Simple> |
1763fe29 |
226 | |
227 | =head1 AUTHOR |
228 | |
eeefd598 |
229 | Andy Grundman, <andy@hybridized.org> |
1763fe29 |
230 | |
11f9b043 |
231 | =head1 CONTRIBUTORS |
232 | |
233 | Simon Elliott <simon@browsing.co.uk> (support for wildcards) |
234 | |
1763fe29 |
235 | =head1 COPYRIGHT |
236 | |
237 | This program is free software, you can redistribute it and/or modify it under |
238 | the same terms as Perl itself. |
239 | |
240 | =cut |