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