metaperl has asked for the wisdom of the Perl Monks concerning the following question:

I have a certain session store value that only needs to be retrieved from the database each time a user authenticates. Specifically, I want to store the user_id for the user that just authenticated.

This is because I will be using it a lot and I dont want to hit the database each time I need to get it.

I wish there were some sort of hook to CGI::Application::Plugin::Authentication which would allow me to do a few things after successful authentication.

  • Comment on CGI::Application::Plugin::Authentication posthook?

Replies are listed 'Best First'.
Re: CGI::Application::Plugin::Authentication posthook?
by scorpio17 (Canon) on Feb 26, 2009 at 15:33 UTC

    I've had to deal with a similar problem. My solution was to use a file-based session object (instead of a database-based session object). Whenever I needed a value (like user_id) I would look first in the file-based session for it. If it wasn't there, I'd pull it from the database, then add it to the file-based session, so it would be there next time. This is basically just a simple caching scheme. It limits your database hits to only the first time data is needed. Every time thereafter it comes from the cache. Note that you can use mysqlite as your file cache, so it still looks like a DB, eventhough it's file-based.

    Just take care to expire sessions upon logout, after updates, etc.

Re: CGI::Application::Plugin::Authentication posthook?
by metaperl (Curate) on Feb 26, 2009 at 14:12 UTC
    I think I figured out a two ways to do this. I can use the Generic driver and simply do some things after the driver authenticates if I write a custom sub... HOWEVER: I just looked at the code for CGIapp::Plugin::Authentication and noticed that it does not pass the authentication instance object to the driver. This means that the generic driver cannot manipulate that object in the authentication process or in a post-authentication process. Here is the line in CGI::Application::Plugin::Authentication in which the driver is called:
    foreach my $driver ($self->drivers) { if (my $username = $driver->verify_credentials(@credential +s)) {
    I would like to see the call to verify_credentials provide the authentication object as well the cgiapp object. Then it will be easy for me to store the user id in a subroutine written using the generic driver.

    in the meantime

    What I can do is subclass CGI::Application::Plugin::Authentication and add a userid method similar to the username method:
    sub username { my $self = shift; $self->initialize; my $u = $self->store->fetch('username'); return $u; }
Re: CGI::Application::Plugin::Authentication posthook?
by leocharre (Priest) on Feb 26, 2009 at 18:26 UTC
    Sometimes I do this kind of thing: (Pseudocode for methods inside your cgiapp)...
    sub userid { my $self = shift; $self->session->param('userid') and return $self->session->param('userid'); my $username = $self->authen->username or return; $self->session->param( 'userid' => ($self->_get_user_id($username) or confess()) ); } sub _get_user_id( my ($self,$username) = @_; # your way of accessing the user id # even if it's heavy, it's called once per session }

    So what happens here, is if our runmode or whatever does not call userid(), you don't load it.

    This can be useful for stressful procedures that you may or may not need.