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

Cookies don't make any sense to me. How are you EVER supposed to set a cookie if you can't do it after you print html headers? How can I get the general idea I have posted below to: 1) Check to see if a cookie exists 2) If it doesn't, print an html login form 3) After they login, it refreshes same page and shows secret content ?

Please don't direct me to other nodes, I've read tons of them on here and none of them explain how this is possible.

if cookie doesn't exist { print html headers print html form check form for authenticity set cookie from login forn } else { print html headers print rest of script }

Title edit by tye

  • Comment on Cookies, how can you set one if it must be done before the header?
  • Download Code

Replies are listed 'Best First'.
•Re: Cookies
by merlyn (Sage) on Dec 24, 2003 at 07:18 UTC
Re: Cookies
by jdtoronto (Prior) on Dec 24, 2003 at 06:19 UTC
    Of course you can't do it AFTER the header is output, the cookie is set as PART OF THE HEADER! The cookie has nothing to do with your login form, it holds a small amount of information that you give to it.
    if cookie doesn't exist { if form input { #process form input validate if validate succeeds { generate cookie output new headers and success page exit } } else { generate headers (without cookie) generate form output all that }
    Well thats one logic for it! Maybe a bit twisted as it is very late here. But YOU control the cookie.

    I would suggest you find a good CGI course, there is a lot of good CGI stuff in the tutorials listed on this site. Anything which explains cookies will explain just how to go about doing this - the go and read the documentation for the CGI module on CPAN, or get the book "Official Guide to Programming with CGI.pm", it is all clearly explained in either place.

    jdtoronto

Re: Cookies
by jeffa (Bishop) on Dec 24, 2003 at 16:27 UTC

    This isn't so bad if you use CGI::Session to do the hard lifting. At the very least read the CGI::Session::Tutorial to get a good foundation (and read merlyn's article as well, if you haven't already).

    Here is a quick-n-dirty CGI script that also uses CGI::Application:

    use CGI::Application; my $webapp = WebApp->new(); $webapp->run(); package WebApp; use strict; use warnings; use CGI::Session; use base 'CGI::Application'; sub setup { my $self = shift; $self->start_mode('index'); $self->mode_param('rm'); $self->run_modes([qw(login index)]); } sub cgiapp_prerun { my $self = shift; my $q = $self->query(); my $session = CGI::Session->new(undef, $q, {Directory=>"/tmp"}); if ($q->param('cm') eq 'Login') { $session->param(logged_in => 1); $session->param(username => $q->param('username')); } elsif ($q->param('cm') eq 'Logout') { $session->delete; } # Redirect to login, if necessary unless ($session->param('logged_in')) { $self->prerun_mode('login'); } if ($session) { my $cookie = $q->cookie(CGISESSID => $session->id); $self->header_props(-cookie=>$cookie); $self->param(session => $session); } } sub login { my $self = shift; my $q = $self->query(); return $q->start_html(-title => 'Login') . $q->start_form() . $q->p('Username: ', $q->textfield('username')) . $q->p('Password: ', $q->password_field('password')) . $q->submit(cm => 'Login') . $q->end_form() . $q->end_html() ; } sub index { my $self = shift; my $q = $self->query(); my $session = $self->param('session'); my $username = $session->param('username'); return $q->start_html(-title => 'Welcome') . $q->p("$username is logged in!") . $q->p($q->a({href=>'?cm=Logout'},"Log out!")) . $q->end_html() ; }
    Ya know ... you kinda sound like webstudorio ... anyways, hope this finally helps. ;)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Cookies
by kiat (Vicar) on Dec 24, 2003 at 06:29 UTC
    If you're using CGI.pm (or any such modules), this may help you...

    use CGI qw(:cgi); # Name of this script, for example my $script = script_name(); my $query = get_param('action') || 'start';' my %actions = ( start => \&do_start, login => \&do_login ); &{ $actions{$query} } sub do_start { my $cookie = cookie('cookie_name'), # Check $cookie value, note that cookies # aren't to be trusted 100% if($cookie) { showsecretcontent(); } else { show_loginpage(); } } sub showsecretcontent { # prints secret content page } sub show_loginpage { # prints login page # Have a hidden field and set its name as 'action' # and its value to 'login' } sub do_login { # process results do_refresh(); } sub do_refresh { my $cookie = ( -name => 'mycookie', -value => 'youareloggedin', -path=>'/', -expires => '+1y' ); print header (-cookie => $cookie); start_html(); print qq~<META HTTP-EQUIV ="Refresh" CONTENT = "2 ; URL=$script">~; print p("You've successfully logged in. Please wait while you're re- +direced..."); end_html(); }
    Hope that helps...
Re: Cookies
by Cody Pendant (Prior) on Dec 24, 2003 at 04:45 UTC
    What exactly is your question?

    Your pseudocode is kind of illogical.

    How about this:

    if cookie doesn't exist { if (the form has been submitted){ check form for authenticity set cookie from login form print html headers print rest of script } else { # form not submitted print html headers print login form } } else { print html headers print rest of script }

    There are three states, right? Cookie doesn't exist and this is a form submission, cookie doesn't exist and this is a form submission, and cookie does exist.

    Does that make sense?



    ($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss') =~y~b-v~a-z~s; print
      Thank you for your help, I've used your code and got pretty far with it, I believe, but I've run into a problem or two. I don't know if the cookie is getting set or not, but it says I'm logged in if I type in the correct password.

      I have url_params that run off this script, but when I'm supposively logged in and I go to a url_param, it errors out saying I have the wrong password. Can you see a problem below with the cookie being sent? And if I reload the page after I log in, I stay logged in. But if I go back to the url using the location bar, it tells me to relog back in.

      Thank you!

      my $adminpassword = "test"; my %cookie; if ( !exists $cookie{'pass'} ) { if ( param() ) { my $adminpass = param('admin'); if ( $adminpass eq $adminpassword ) { my $cookiename = cookie( -name => 'cookie', -value => 'loggedin', -expires => '+1h' ); print header, start_html(); # print rest of page here print "you are logged in"; } } else { print header, start_html(); print "Incorrect password, please click back and try again +"; exit; } } else { print header, start_html(); print start_form(), table( Tr( td("Admin Password: "), td( textfield( -name => 'admin', -size => 10 ) ) ), Tr( td(), td(submit) ), ), end_form(), hr(); } }
        I have found that Mozilla is very useful for tracking the setting and sending of cookies. All you need to do is turn on the 'Ask me before setting cookies' option in the privacy settings and you get an informational dialog each time that a cookie is set. You can then use the cookie manager to inspect the cookies that have been set.

        You may also want to dump the HTTP headers that your app received as HTML comments while you are building and debugging your app. Using Data::Dumper on your cgi object(or other objects) is also useful.

        IE requires the path be set in your cookie..

        my $cookiename = cookie( -name => 'cookie', -value => 'loggedin', -expires => '+1h' -path => '/', );

        cheers,

        J