[dancer-users] Dancer::Session and cookie path of session cookie

Jens Rehsack rehsack at gmail.com
Thu Dec 27 16:14:38 GMT 2012


On 27.12.12 17:14, Jens Rehsack wrote:
> Hi David, hi Dancer users,
>
> as talked in mid of December on irc.perl.org/#dancer I had some
> trouble with Dancer::Session::Cookie and the cookie path.
>
> I used 'session_cookie_path' set to a restricted area of a dancer
> app (requirement - don't ask), but on some circumstances the path
> was used or not.
>
> Later I figured out that Dancer::Session forces cookie rewrite
> using Dancer::Session::Abstract->write_session_id and when a
> session key/value was updated, Dancer::Session::Cookie->flush
> uses it's own cookie update mechanism.
>
> First I added the ability of restricting session cookie path
> to Dancer::Session::Abstract (and fix some function calls into
> methods). Then I forgot to install the fix and search for some
> hours the test failure in upated Dancer::Session::Cookie.
>
> This mail includes the patches for Dancer itself - follow up
> mail includes the patch for Dancer-Session-Cookie dist.
>
> Would be great if you could review and/or apply or find someone
> who could.
>
> Thanks in advance,
> Jens
>
> PS: Happy New Year, everyone!


-- 
Jens Rehsack
-------------- next part --------------
From 054b7fb4bfcef1e46fa0704c8c9e899125b14aad Mon Sep 17 00:00:00 2001
From: Jens Rehsack <sno at netbsd.org>
Date: Thu, 27 Dec 2012 16:52:37 +0100
Subject: [PATCH 1/2] fix for write_session_id with session_path requires
 Dancer 1.311

---
 Makefile.PL                  |    2 +-
 lib/Dancer/Session/Cookie.pm |    8 --------
 2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/Makefile.PL b/Makefile.PL
index 37d3472..5b17252 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -20,7 +20,7 @@ WriteMakefile(
         'Crypt::CBC'      => 0,
         'String::CRC32'   => 0,
         'Crypt::Rijndael' => 0,
-        'Dancer'          => 1.130,
+        'Dancer'          => 1.1311,
     },
     dist                => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
     clean               => { FILES => 'Dancer-Session-Cookie-* t/logs' },
diff --git a/lib/Dancer/Session/Cookie.pm b/lib/Dancer/Session/Cookie.pm
index c0d3ccb..3bc6c30 100644
--- a/lib/Dancer/Session/Cookie.pm
+++ b/lib/Dancer/Session/Cookie.pm
@@ -60,14 +60,6 @@ sub create {
     return Dancer::Session::Cookie->new(id => 'empty');
 }
 
-
-# session_name was introduced to Dancer::Session::Abstract in 1.176
-# we have 1.130 as the minimum
-sub session_name {
-    my $self = shift;
-    return eval { $self->SUPER::session_name } || setting("session_name") || "dancer.session";
-}
-
 sub flush {
     my $self = shift;
 
-- 
1.7.10.2 (Apple Git-33)
-------------- next part --------------
From 9f7b663221d630ee1534dc062fe1a84d779a7b16 Mon Sep 17 00:00:00 2001
From: Jens Rehsack <sno at netbsd.org>
Date: Thu, 27 Dec 2012 16:55:01 +0100
Subject: [PATCH 2/2] - do not shoot cross hole
 (Dancer::Session::Abstract->write_session_id <->
 Dancer::Session::Cookie->flush (own set_cookie call)) -
 "better" error messages on wrong settings

---
 lib/Dancer/Session/Cookie.pm |   54 +++++++++++++++++++++++++-----------------
 t/01-session.t               |    2 +-
 t/02-configfile.t            |    2 +-
 t/03-path.t                  |   18 +++++++++-----
 4 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/lib/Dancer/Session/Cookie.pm b/lib/Dancer/Session/Cookie.pm
index 3bc6c30..ab6dff0 100644
--- a/lib/Dancer/Session/Cookie.pm
+++ b/lib/Dancer/Session/Cookie.pm
@@ -4,39 +4,45 @@ use strict;
 use warnings;
 use base 'Dancer::Session::Abstract';
 
+use Carp qw(croak);
+
 use Crypt::CBC;
 use String::CRC32;
 use Crypt::Rijndael;
 
-use Dancer ();
+use Dancer 'set';
 use Dancer::Config 'setting';
 use Storable     ();
 use MIME::Base64 ();
 
 use vars '$VERSION';
-$VERSION = '0.15';
+$VERSION = '0.16';
 
-# crydec
-my $CIPHER = undef;
+my %CIPHER;
 
+# crydec
 sub init {
-    my ($class) = @_;
+    my ($self, @args) = @_;
 
     my $key = setting("session_cookie_key")  # XXX default to smth with warning
-      or die "The setting session_cookie_key must be defined";
+      or croak "The setting 'session_cookie_key' must be defined";
+
+    if (my $session_cookie_path = setting("session_cookie_path")) {
+	my $session_path = setting("session_path");
 
-    $CIPHER = Crypt::CBC->new(
+	$session_path and $session_cookie_path and $session_path ne $session_cookie_path
+	  and croak "The settings 'session_cookie_path' ($session_cookie_path) and 'session_path' ($session_path) must not be both defined";
+
+	set session_path => $session_cookie_path;
+    }
+
+    defined $CIPHER{$key}
+      or $CIPHER{$key} = Crypt::CBC->new(
         -key    => $key,
         -cipher => 'Rijndael',
     );
-}
-
-sub new {
-    my $self = Dancer::Object::new(@_);
 
-    # id is not needed here because the whole serialized session is
-    # the "id"
-    return $self;
+    $self->SUPER::init(@args);
 }
 
 sub retrieve {
@@ -60,6 +66,8 @@ sub create {
     return Dancer::Session::Cookie->new(id => 'empty');
 }
 
+sub build_id { "" } # will be filled in flush
+
 sub flush {
     my $self = shift;
 
@@ -67,12 +75,8 @@ sub flush {
     delete $self->{id};
     my $cipher_text = _encrypt(Storable::freeze($self));
 
-    my $session_name = $self->session_name;
-    Dancer::set_cookie(
-        $session_name   => $cipher_text,
-        path  => setting("session_cookie_path") || "/",
-        secure=> setting("session_secure"),
-    );
+    $self->write_session_id($cipher_text);
+
     $self->{id} = $cipher_text;
 
     return 1;
@@ -90,10 +94,13 @@ sub _encrypt {
 
     my $crc32 = String::CRC32::crc32($plain_text);
 
+    my $key = setting("session_cookie_key")  # XXX default to smth with warning
+      or die "The setting session_cookie_key must be defined";
+
     # XXX should gzip data if it grows too big. CRC32 won't be needed
     # then.
     my $res =
-      MIME::Base64::encode($CIPHER->encrypt(pack('La*', $crc32, $plain_text)),
+      MIME::Base64::encode($CIPHER{$key}->encrypt(pack('La*', $crc32, $plain_text)),
         q{});
     $res =~ tr{=+/}{_*-};    # cookie-safe Base64
 
@@ -105,9 +112,12 @@ sub _decrypt {
 
     $cookie =~ tr{_*-}{=+/};
 
+    my $key = setting("session_cookie_key")  # XXX default to smth with warning
+      or die "The setting session_cookie_key must be defined";
+
     $SIG{__WARN__} = sub {};
     my ($crc32, $plain_text) = unpack "La*",
-      $CIPHER->decrypt(MIME::Base64::decode($cookie));
+      $CIPHER{$key}->decrypt(MIME::Base64::decode($cookie));
     return $crc32 == String::CRC32::crc32($plain_text) ? $plain_text : undef;
 }
 
diff --git a/t/01-session.t b/t/01-session.t
index 6db242e..ab89fac 100644
--- a/t/01-session.t
+++ b/t/01-session.t
@@ -15,7 +15,7 @@ BEGIN {
 my $session;
 
 throws_ok { $session = Dancer::Session::Cookie->create }
-    qr/session_cookie_key must be defined/, 'requires session_cookie_key';
+    qr/'session_cookie_key' must be defined/, 'requires session_cookie_key';
 
 set session_cookie_key => 'test/secret*@?)';
 lives_and { $session = Dancer::Session::Cookie->create } 'works';
diff --git a/t/02-configfile.t b/t/02-configfile.t
index bde7a37..770ed92 100644
--- a/t/02-configfile.t
+++ b/t/02-configfile.t
@@ -18,7 +18,7 @@ plan tests => 3;
 my $session;
 
 throws_ok { $session = Dancer::Session::Cookie->create }
-    qr/session_cookie_key must be defined/, 'still requires session_cookie_key';
+    qr/'session_cookie_key' must be defined/, 'still requires session_cookie_key';
 
 set confdir => "$FindBin::Bin/data";
 ok(-r File::Spec->catfile(setting('confdir'), 'config.yml'),
diff --git a/t/03-path.t b/t/03-path.t
index 004c279..7a94f56 100644
--- a/t/03-path.t
+++ b/t/03-path.t
@@ -9,26 +9,32 @@ use Dancer;
 my $CLASS = 'Dancer::Session::Cookie';
 use_ok $CLASS;
 
+my $Session_Name = Dancer::Session::Cookie->session_name;
+
 note "test setup"; {
     set session_cookie_key => "The dolphins are in the jacuzzi";
 }
 
 
 note "default path"; {
-    my $session = Dancer::Session::Cookie->create;
-    $session->flush;
+    set session => "cookie";
+    session foo => "bar";
 
-    is cookies->{"dancer.session"}->path, "/";
+    my $session_cookie = Dancer::Cookies->cookies->{ $Session_Name };
+    is $session_cookie->path => "/";
 }
 
 
 note "set the path"; {
+    delete Dancer::Cookies->cookies->{ $Session_Name };
+
+    set session => "cookie";
     set session_cookie_path => "/some/thing";
 
-    my $session = Dancer::Session::Cookie->create;
-    $session->flush;
+    session up => "down";
 
-    is cookies->{"dancer.session"}->path, "/some/thing";
+    my $session_cookie = Dancer::Cookies->cookies->{ $Session_Name };
+    is $session_cookie->path => "/some/thing";
 }
 
 done_testing;
-- 
1.7.10.2 (Apple Git-33)


More information about the dancer-users mailing list