[Catalyst] Securing a connection
Jesse Sheidlower
jester at panix.com
Tue May 14 17:37:04 GMT 2013
I've recently upgraded my Cat to 5.9, and in the process decided to
switch from the deprecated Catalyst::Plugin::RequireSSL to
C::ActionRole::RequireSSL. Somewhere along the line, something stopped
working in my secure-connection activity, and no one found an answer in
some IRC chat so I thought I'd try here, with an additional question or
two.
For debugging purposes now I'm just trying the most basic thing--making
my login secure. If I go to http://example.com/myapp, I get routed to
http://example.com/myapp/login (not https, which is what I expect, since
the Does('RequireSSL') is in the login method). When I enter
login/password info, the app crashes with a "Cannot secure request on
POST" error. (I don't understand this error anyway--why can't you secure
a POST, or what are you supposed to do so that login or other sensitive
info is going over https?)
Apart from login, the only things I want to be secure are viewing and
editing of user info. In production I'm running under nginx/FastCGI, and
it's mostly how I've been testing this too (on a VM). Oh, if I manually
enter an https address, it works, so it doesn't seem to be a server
problem.
Thanks for any ideas. This isn't something that I thought should be so
hard....
Code below. The (straightforward) login method, from my User controller:
use parent qp/Catalyst::Controller::ActionRole/;
# ....
sub login :Path('/login') Does('RequireSSL') {
my ($self, $c) = @_;
# Get the username and password from form
my $username = $c->request->params->{username} || "";
my $password = $c->request->params->{password} || "";
# If the username and password values were found in form
if ($username && $password) {
# Attempt to log the user in
if ($c->authenticate({ login => $username, password => $password }))
{
# If successful, then let them use the application
$c->user->last_login(\'now()');
$c->user->update;
if ( $c->req->address =~ $c->config->{permanent_login_regex} ) {
$c->session->{remember_me} = 1;
}
my $redirect = $c->session->{orig_uri} || $c->uri_for('/');
$c->session->{orig_uri} = undef;
$c->response->redirect( $redirect );
return;
} else {
$c->stash->{message} = "You have entered an invalid
username/password combination";
}
}
# If either of above don't work out, send to the login page
$c->stash->{title} = "Application login";
$c->stash->{template} = 'login.tt';
}
I'm not going to bother showing my auto() methods, though they're here
if anyone cares: http://paste.scsys.co.uk/248078 The main thing is that
if there's no user, it redirects to /login (not just forwards there).
The login form is the usual:
<form method="post" action=" [% c.uri_for('/login') %] " name="login">
And here's the (messy, sorry) debug output, from the testing server (and
thus not able to use SSL, but still showing the 500 error on the POST.
[info] *** Request 1 (0.167/s) [21253] [Tue May 14 11:57:37 2013] ***
[debug] Path is "/"
[debug] "GET" request for "/" from "127.0.0.1"
[debug] Created session "7f752088d13d623783c5d2904a51fa33fc41b2ae"
[debug] ***Root::auto User not found, forwarding to /login
[debug] Redirecting to "http://localhost:3000/login"
[debug] Response Code: 302; Content-Type: text/html; charset=utf-8;
Content-Length: 306
[info] Request took 0.063867s (15.658/s)
.------------------------------------------------------------+-----------.
| Action |
Time |
+------------------------------------------------------------+-----------+
| /auto |
0.056214s |
| /end |
0.000609s |
| -> /render |
0.000358s |
'------------------------------------------------------------+-----------'
[info] *** Request 2 (0.182/s) [21253] [Tue May 14 11:57:42 2013] ***
[debug] Path is "login"
[debug] "GET" request for "login" from "127.0.0.1"
[warn] Would've redirected to SSL
[debug] Rendering template "login.tt"
[debug] Found sessionid "7f752088d13d623783c5d2904a51fa33fc41b2ae" in
cookie
[debug] Restored session "7f752088d13d623783c5d2904a51fa33fc41b2ae"
[debug] Response Code: 200; Content-Type: text/html; charset=utf-8;
Content-Length: 2347
[info] Request took 0.047926s (20.866/s)
.------------------------------------------------------------+-----------.
| Action |
Time |
+------------------------------------------------------------+-----------+
| /auto |
0.001897s |
| /user/auto |
0.000134s |
| /user/login |
0.000239s |
| /end |
0.037722s |
| -> /render |
0.036557s |
| -> NewWords::View::TT->process |
0.035981s |
'------------------------------------------------------------+-----------'
[info] *** Request 3 (0.115/s) [21253] [Tue May 14 11:57:57 2013] ***
[debug] Path is "login"
[debug] "POST" request for "login" from "127.0.0.1"
[debug] Body Parameters are:
.-------------------------------------+--------------------------------------.
| Parameter |
Value |
+-------------------------------------+--------------------------------------+
| password |
testpassword |
| submit |
Login |
| username |
testuser |
'-------------------------------------+--------------------------------------'
[warn] Would've redirected to SSL
[debug] Found sessionid "7f752088d13d623783c5d2904a51fa33fc41b2ae" in
cookie
[debug] Restored session "7f752088d13d623783c5d2904a51fa33fc41b2ae"
[error] Cannot secure request on POST
[debug] Redirecting to "http://localhost:3000/"
[debug] Response Code: 500; Content-Type: text/html; charset=utf-8;
Content-Length: 154248
[info] Request took 0.123818s (8.076/s)
.------------------------------------------------------------+-----------.
| Action |
Time |
+------------------------------------------------------------+-----------+
| /auto |
0.001568s |
| /user/auto |
0.000078s |
| /user/login |
0.045757s |
| /end |
0.000485s |
| -> /render |
0.000258s |
'------------------------------------------------------------+-----------'
More information about the Catalyst
mailing list