Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Persistent login session with restricted access

by kgish (Acolyte)
on Oct 09, 2004 at 20:40 UTC ( [id://397907]=perlquestion: print w/replies, xml ) Need Help??

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

I want to make my website available to all visitors, but restrict its use via logins. By default there would be a login link available at the top of each page.

The user clicks this link in order to login (the first time), and if successful will be known for the rest of the session via a given username and a "~logged-in" variable. This sessions will timeout after 30 minutes idle time.

If the user wishes he can enable automatic login through the use of cookies which is the usual checkbox he can check during the login form.

In addition to being able to access the whole site, the logged-in users will also be able to enter user-specific pages for entering data, e.g. hours of a timesheet.

Other visitors can view these same timesheets, but if not logged in as the owner can only have read-only access, e.g. I can disable or hide certain buttons and make all input text fields readonly.

The logged-in person can logout at anytime, after which he must login again to make changes.

Also, I should have admin access to edit the usernames, passwords, emails etc. And of course, the individual users should be able to change their own settings here.

Is there an example cgi script which accomplishes this, e.g. using CGI::Session or whatever?

Thanks in advance for the time and attention.

Replies are listed 'Best First'.
Re: Persistent login session with restricted access
by Anneq (Vicar) on Oct 10, 2004 at 14:06 UTC

    kgish,

    I use CGI::Application and Template::Toolkit to do the heavy lifting. Instead of giving you the code, I'll give you a description of how I approached the same problem (http://artwest.ca). If you write it yourself, you'll have a much better understanding of it.

    CGI::Application - setup():

    My C::A setup() has two run modes, one for login/register validation and one for everything else. Also in setup(), I open up a config file and bring in some default variables.

    CGI::Application - cgiapp_prerun():

    First, an existing session is opened or a new one is created, depending on the presenence of a session cookie in the request. The new or existing session id is then set in the outgoing HTTP header. If the run mode is set to 'logout', the session param 'logged_in' is set to false, the user security level is set to the lowest, and the run mode is reset to default. If the run mode or any other desired query or session parameters are not set, they are now set to their default values. Lastly, a sub in a separate module is called to do things if the user selected to change one of their display preferences (e.g., font size or theme color).

    C::A - validate():

    This run mode calls a sepatare module to validate a login or registration request and retuns a message if errors occurred. The authentication module logs in or registers the user if appropriate. validate() then calls a sparate module to build the page, including any login or registration errors, and a web page is returned (the page returned depending on user's security level).

    C::A - normal():

    This method calls a sparate module to build the page, and a web page is returned (the page returned depending on user's security level).

    Template::Toolkit:

    I use TT for page layout and to automatically build navbars. With TT, its easy to place a login form (or a logout url) on every page. As well, if you store your registration information in tables, TT's DBI plugin simplifies administering registration information. TT has a great O'Reilly book that I would recommend purchasing. Having the reference has sped up my development time and reduced my pain significantly.

    Restricting Access:

    I use a simple table of security levels per each major content section. So the user must have the same or greater security level then the content section in order to view the requested page. To prohibit access to content other than through my index.cgi script, I use .htaccess files in protected directories.

    I hope this gives you some idea where to start. Note, however, that I'm not a professional programmer or web developer so there are bound to be some security problems or better ways to do it.

    Good luck,

    Anne

      The way I've seen most successfully done is this:
      1. Have a set of runmodes that do what you want. They do not worry about security.
      2. Have a standard login page.
      3. Use the cgiapp_prerun() method to check if the person is logged in correctly. If they are not and they requested a page that requires being logged in, redirect them to the login page.
      4. Otherwise, you don't do anything. The user was validated correctly, so the normal flow of events should continue. I.e., the page requested should be rendered.

      Your idea about having a separate file and all that ... why be so complicated? cgiapp_prerun() cannot be circumvented by the user. Your method, theoretically, can be, especially if you call another cgi script and return its return value.

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        dragonchild,

        1. The reason I have a runmode for validation is because I want the user to be able to login or logout from any page, similar to the perlmonks site. So the "login" template component is part of every page rendered. After validation, the previously requested page is served up automatically without the user requesting it again. My default run mode is the only other one required at at the moment because it is the only one needed to serve up simple pages. Other run modes will be added as more complex functionaly is added to the site.
        2. As stated above, if a user requested a page that required authentication, they would get a notification that they must be logged in to view that page. After logging in, the previously requested page automatically displays without having to request it again.
        3. My cgiapp_prerun() only checks to see if the person is logged out and then resets the session and displays the home page. I didn't see the need to check if a person is logged in, because the site is based on levels of authorization (e.g., anonymous, members, executive, administrators). For example, users not logged in can access the anonymous level pages. My cgi page building module checks the authorization level of the user against that of the page to determine whether the page should be served. I looked into redirecting but didn't see how to do this in a way that made sense with how my site is structured. I suspect that I'm missing something here but I couldn't see how it would work for me. I use a CGI query parameter that is placed in the urls of dynamically generated navbars to indicate to my site what resourse is being requested. Since these are all, thus far, simple content without forms or other functionality, they are served by my default run mode. I wanted to keep it simple and it works so far. Maybe I'll see your point (and have to refactor the code) when I begin to add more functionality.
        4. I use a separate .htaccess file to prohibit people from guessing the layout of my content and typing in those guesses in the url, thus bypassing my index.cgi script. This was a security threat that I had to address and I couldn't think of any other way to do it. I'm not using HTTP Authentication.

          I'm still looking into redirecting, but I don't fully understand how to it properly in a way that makes sense here. Any advise would be appreciated.

          Thanks for your help,

          Anne

      Okay Anne, this looks really promising. I will give it a go and see if I can create something worthy of your respect. Thanks alot.
Re: Persistent login session with restricted access
by Jaap (Curate) on Oct 09, 2004 at 21:36 UTC
    Dear kgish,

    Please use some newlines when you post, you can make newlines with <br>.
    Also, you say you want a login, you provide the potential solution, what is it really that you want me to say here? You want me to write the script for you?

    These comments are inteded to help you make better posts in the future, please do not be offended. If you are, /msg me and i will take appropriate action on my post.
      Sure, a script would be nice, but just a simple bare-minimum example is all I need. (No I am not offended, e.g. I fixed it for you didn't I?)
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://397907]
Approved by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2024-03-28 17:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found