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

Hello monks! I have a currently working web app (that I've inherited) on a server that I'm trying to replicate the basic architecture onto another server. The app is using CGI::Application::Plugin::Session. I'm able to successfully login and create a populated session file on the new server, however, when I try to perform any functions within the app, I 'lose' the session and it takes me back to my login screen. No errors in the apache log.

Since the code already works on another server, I THINK that it's a permissions problem. ??? What do I want my umask permissions to be set to while still being secure?

Or am I missing something else?

Replies are listed 'Best First'.
Re: session file umask
by samtregar (Abbot) on Jan 12, 2009 at 19:50 UTC
    Pretty unlikely to be a permissions problem if you're not seeing anything in the error log. I'd look at the cookies being generated - do they have the correct domain? Are they being sent back to the server on subsequent requests?

    -sam

      Interesting observation...I hadn't thought of the cookies.

      It looks like the cookies have the right domain. Is the folder path important? How do I tell if they are being sent back to the server?

      thanks

        Yes, the path setting on the cookie matters - it tells the browser which part of the site the cookie applies to. Set it wrong and you won't get your cookie back!

        I mainly use two tools for debugging cookie problem - first, Firefox with the Web Developer addon. This gives you a screen where you can see what cookies are set and all their parameters. Failing that I pull out the big gun - wireshark. It's a network-level protocol examiner and you can use it to see exactly what the client and server are actually saying to each other. The learning curve is steep but sometimes you really need to see what's actually on the wire to solve a problem.

        -sam

Re: session file umask
by bradcathey (Prior) on Jan 13, 2009 at 01:55 UTC

    I basically asked the same question last week. Take a look.

    —Brad
    "The important work of moving the world forward does not wait to be done by perfect men." George Eliot
      I'm not seeing where that thread matches my scenario. I'm not doing any redirects and my problem isn't in the code since the same code works on another server.
Re: session file umask
by scorpio17 (Canon) on Jan 13, 2009 at 15:29 UTC

    I usually use a cookie path of just '/'. This makes the cookie visible to the entire site. If you have some need to restrict cookie usage to just a particular path, you can try '/' temporarily, just to debug.

    Note that sessions can be stored in files or databases, etc. There's a lot of variation available in the configuration. If you are storing the sessions in files, then permission issues can cause problems. The web server usually runs as something like 'nobody', so that user must be able to write the files, have permission to the directory being written to, etc. Lots of people put session files somewhere like /tmp/sessions, but on in a shared host environment, every other site on the same host can potentially see your session data (or accidentally clobber it).

    I like using the database method better, but it can be expensive in terms of DB queries (every page view results in multiple hits: a read to check the current login/logout status, then a write to update the time until expiration, etc.). In production usage you want to go with the 'Storable' data store, but for debugging use the default (DataDumper) because the contents of the session object will just be simple ASCII text.

    Another 'gotcha' I've encountered occurrs when you try to redirect to a secure page (https) for login, then redirect back to http afterwards. If the https domain is different, then the cookie is written on that domain, and thus not visible elsewhere.

    Here's an example:

    If your home page is here:

    http://www.example.com/home

    and you have a login link that takes you here:

    https://www.secure.com/login

    and then you redirect back to the home page after login (and let's assume you have different content for logged-in versus logged out users, and you depend on the session to determine which is which).

    So you can have a successful login, but the cookie containing the session id which points to this state is only visible on the .secure.com domain, not the .example.com domain. So you still get the logged-out version of the home page.

    The easy fix is to either do whatever necessary to have a secure url in the same domain:

    https://www.example.com

    Or else, make your login link point a script that does the following: create/fetch current session id and store it in a cookie. Then redirect to the login page (script you previously pointed login link to) with the session id attached as a url parameter (or, better, don't use a link, make it like a form, and send the id as a hidden parameter). This way the secure host can retrieve/modify the session data without using the cookie. Or, you can create another cookie, on the secure host, containing the same session id, but you need some way of passing that id from one host to the other, else it won't see it (and since you're using CAP:Session, it will actually create a new session automatically, which isn't what you want).

      I tried the '/' path, and I'm getting the same results.

      This web app is for an internal intranet site, so I didn't bother with securing the login page or any subsequent pages. ...I'm not changing the domain, either.

      I'd thought about the DB, but eliminated that idea for the very reasons you mentioned...plus for an internal site, the added security wasn't important enough for the overhead. Not to mention, I didn't want to go through the extra effort of setting up and learning postgresql on this server ;)

        If a simple (working) demo would be useful, some time back I wrote a tutorial showing how to create a basic login page:

        A Beginners Guide to CGI::Application

        If you want file-based sessions, change this part of Login.pm:

        CGI_SESSION_OPTIONS => [ "driver:mysql;serializer:Storable;id:md5", $self->query, {Handle => $self->dbh}, ],

        To this:

        CGI_SESSION_OPTIONS => [ "driver:File", $self->query, {Directory => "/tmp/sessions"}, ],

        Then, assuming your web server runs as 'nobody', do this:

        mkdir /tmp/sessions chown nobody:nobody /tmp/sessions cmod 755 /tmp/sessions

        One final gotcha - make sure you've got all the same versions of all your modules being used on both servers. I try to install on my modules locally, then I can just tar up the modules directory and copy it to a new server, and be sure that I'm running the exact same (noncore) stuff everywhere.