简体   繁体   中英

How do you use Plack::Middleware::Session with a Starman Server?

I have a Starman based server -

#!/usr/bin/perl
use strict;
use warnings;
use Data::Printer;
use Plack::Builder;

my $app = sub {
    my $env = shift;
    my $session = $env->{'psgix.session'};

    # Print environment variables
    p($env);

    return [
        200,
        [ 'Content-Type' => 'text/plain' ],
        [ "Hello, you've been here for ", $session->{counter}++, "th   time!" ],
    ];
};

my $default = sub {
    my $env = shift;
    p($env);
    return [
        '200', [ 'Content-Type' => 'text/html' ],
        ["Welcome to default page"],
    ];
};

builder {
    mount "/validate" => builder {
        enable "Middleware::Authentication"
        enable "Session";
        $app;
    };
    mount "/" => builder { $default };
};

My own middleware "Authentication" authenticate the user and return session information(expiry time, session key etc) for the session management, So how can i make use of these information in the Session Middleware?

If I understand right, your problem is only in the order of the middleware. Enable the Session before your Auth .

Check the following, using the File storage, the sessions are stored persistently. Try it, restart your Starman and the counter will be reloaded. (I using inline middleware as an replacement to your Authentication .)

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Printer;
use Plack::Builder;

my $app = sub {
    my $env = shift;
    my $session = $env->{'psgix.session'};
    return [
        200,
        [ 'Content-Type' => 'text/html' ],
        [
            "My app page is visited ",
            $session->{counter}++,
            "th times! Validation is done at:",
            $session->{mwaretime},
            q{<br><a href="/validate">go validate again</a> --- <a href="/">reload this page</a>}
        ],
    ];
};

my $validate = sub {
    my $env = shift;
    my $session = $env->{'psgix.session'};
    $session->{counter} = 0;
    return [
        '200', [ 'Content-Type' => 'text/html' ],
        [
            "Resetting the counter:",
            $session->{counter},
             ". Time from middleware: ",
            $session->{mwaretime},
            q{<br> <a href="/validate">reload this page</a> --- <a href="/">go to index</a> }
        ],
    ];
};

builder {
    #the session will be stored persistently
    #enable the Session BEFORE your middleware
    enable 'Session', store => 'File';

    mount "/validate" => builder {
        #enable "Authentication";
        #following is same as an middleware
        enable sub {
            my $app = shift;
            return sub {
                my $env = shift;
                my $session = $env->{'psgix.session'};
                $session->{mwaretime} = time();
                $app->($env);
            };
        };
        #end of the middleware
        $validate;
    };
    mount "/" => $app 
};

From your question, it's hard to tell what your requirements look like exactly. But if you want this much control over session management, it might be better to write your own middleware. That said, there are some ways to adapt Plack::Middleware::Session to certain scenarios. But most of them use more or less undocumented features. This means that you have to familiarize yourself with the source, and that these features might be changed or go away in later versions.

If you want to provide your own session keys, you can pass a custom SID generator and validator to Plack::Session::State :

enable 'Session',
    state => Plack::Session::State->new(
        sid_generator => $my_generator,
        sid_validator => $my_validator,
    );

The documentation of sid_generator says basically to "just read the source".

You can also implement your own Plack::Session::Store backend. But in this case, it probably makes more sense to switch to a custom solution.

Regarding cookie expiration times, you can set the expires option in $env->{'psgix.session.options'} before a new cookie is created:

$env->{'psgix.session.options'}{expires} = $my_expires;

This is not a timeout but a time in seconds since the UNIX epoch, or any value accepted by Cookie::Baker .

Maybe you should just rethink if your authentication middleware really has to generate the session keys. Like @jm666 said, you typically run the session middleware before authentication. Then your authentication code can access all the session information. The session ID is typically an implementation detail of session management that doesn't have to concern other parts of your code. To change the expiration time, see my answer to this question .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM