Fixed the README to actually contain the correct docs
[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
d5e430c2 7our $VERSION = '0.02';
1763fe29 8
9__PACKAGE__->mk_accessors( '_require_ssl' );
10
11=head1 NAME
12
13Catalyst::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
29Use this plugin if you wish to selectively force SSL mode on some of your web pages,
30for example a user login form or shopping cart.
31
32Simply place $c->require_ssl calls in any controller method you wish to be secured.
33
34This plugin will automatically disable itself if you are running under the standalone
35HTTP::Daemon Catalyst server. A warning message will be printed to the log file whenever
36an SSL redirect would have occurred.
37
38=head1 WARNINGS
39
40If you utilize different servers or hostnames for non-SSL and SSL requests, and you rely
41on a session cookie to determine redirection (i.e for a login page), your cookie must
42be visible to both servers. For more information, see the documentation for the Session plugin
43you are using.
44
45=head1 CONFIGURATION
46
47Configuration is optional. You may define the following configuration values:
48
49 https => $ssl_host
50
51If your SSL domain name is different from your non-SSL domain, set this value.
52
53 http => $non_ssl_host
54
55If you have set the https value above, you must also set the hostname of your non-SSL
56server.
57
58 remain_in_ssl
59
60If you'd like your users to remain in SSL mode after visiting an SSL-required page, you can
61set this option to 1. By default, users will be redirected back to non-SSL mode as soon as
62possible.
63
64=head2 METHODS
65
66=over 4
67
68=item require_ssl
69
70Call require_ssl in any controller method you wish to be secured.
71
72 $c->require_ssl;
73
74The browser will be redirected to the same path on your SSL server. POST requests
75are never redirected.
76
77=cut
78
79sub 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
95Redirect back to non-SSL mode if necessary.
96
97=cut
98
99sub 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
119Setup default values.
120
121=cut
122
123sub 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
139Generate the redirection URI.
140
141=cut
142
143sub _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
173When viewing an SSL-required page that uses static files served from the Static plugin, the static
174files are redirected to the non-SSL path. It may be possible to work around this by checking the
175referer protocol, but currently there is no way to determine if a file being served is static content.
176
177For best results, always serve static files directly from your web server without using the Static
178plugin.
179
180=head1 SEE ALSO
181
182L<Catalyst>
183
184=head1 AUTHOR
185
186Andy Grundman, C<andy@hybridized.org>
187
188=head1 COPYRIGHT
189
190This program is free software, you can redistribute it and/or modify it under
191the same terms as Perl itself.
192
193=cut
194
1951;