ted.byers has asked for the wisdom of the Perl Monks concerning the following question:

I am using the following CGI packages

use CGI; use CGI::Session;

Google has not been a friend in this quest, turning up much more noise than anything else. Here is what I tried:

print $cgi->header(-cookie=>$tokcookie); print $cgi->redirect( -location => $base_url, -cookie => $cookie

And here is the HTML I got.

<html> <head></head> <body>Status: 302 Found Set-Cookie: CGISESSID=5b74d67873211375e3aef2ed +004bd22d; path=/; expires=Sat, 22-Aug-2015 03:04:12 GMT Date: Sat, 22 + Aug 2015 02:34:12 GMT Location: https://gateway.onsoftarchpayments.c +om/cgi-bin/np.pl </body> </html>

Firebug actually claims no cookie was received. In the body of the HTML I received, I see the value of the variable $cookie. However, it seem the cookie in $tokcookie is lost.

I really need be able to pass two cookies, as the $cookie is my session cookie, which is used for the obvious purpose. The cookie $tokcookie is a special cookie used to defend against cross site request forgery (check out the OWASP web site if you're curious about this, but the details are not relevant for this question). This cookie, too, is essential.

I have been through all the documentation I could find for this, and while there are lots of examples/discussion or passing one cookie in a redirection using function $cgi->redirect, I have yet to find any discussion or mention of passing two cookies in a redirection. Hence the question: "What do I need to change in order to be able to pass two cookies in this redirection?"

Thanks

Ted

Replies are listed 'Best First'.
Re: Submiting multiple cookies on a redirect - how?
by 1nickt (Canon) on Aug 22, 2015 at 03:48 UTC

    Hi ted.byers, see the CGI docs:

    To create multiple cookies, give header() an array reference: $cookie1 = cookie(-name=>'riddle_name', -value=>"The Sphynx's Question"); $cookie2 = cookie(-name=>'answers', -value=>\%answers); print header(-cookie=>[$cookie1,$cookie2]);
    The way forward always starts with a minimal test.
Re: Submiting multiple cookies on a redirect - how?
by hippo (Archbishop) on Aug 22, 2015 at 08:52 UTC

    Cookies are set in the HTTP header, not in the HTML. If you see a cookie set in the HTML that's an error because it is too late. Your first problem above is that you are trying to set the HTTP header twice - once with the header call and once with the redirect call. That's why you see the headers set by redirect in the HTML - they have been set too late.

    So, to set multiple cookies in a redirect pass an arrayref like so:

    print $cgi->redirect ( -location => $base_url, -cookie => [$cookie, $tocookie] );

    Make sure you do not call header.

      Thanks this solved one problem, but revealed another.

      I am finding that somehow the cokkie value for the second cookie is the name of the variable that held it rather than the actual value.

      In my login script, I have the following to make the cookie:

      ($sessid,$tokcookie) = setup_session($userID, $userType); my $cookie = $cgi->cookie(-name => 'CGISESSID', -value => $sessid, - +expires => "+30m"); print $cgi->redirect( -location => $base_url, -cookie => [$cookie,$tokcookie] );

      setup_session is a function defined at the end of the login script, storing in the session table things like user ID, user type, and other values not relevant to this question. $cookie gets the proper name and value. However, $tokcookie does not. Within setup_session, there is the following call

      my ($session,$tok_cookie) = DBUtility::get_session($cgi,$uid);

      And there are the relevant parts of that function:

      $rv = CGI::Session->new('driver:mysql',$query,{ DataSource => "db +i:mysql:database=profitorius;host=$hostname", User +=> 'xxxxxxxxxxx', Password +=> 'yyyyyyyy' }); my $hash = $pbkdf2->generate($enc_csrfp_str); $rv->param('enccsrfp',$hash); $cookie = $query->cookie(-name=>'H_VAL', -value=>$hash, -httponly => 1, -expires => "+30m", -secure => 1); return ($rv,$cookie);

      $rv is the session, with the data retrieved from the DB. $enc_csrfp_str is a complex string, which includes a GUID (in string form, so only ASCII characters) and the user's ID. The variable $hash gets the encrypted value of $enc_csrfp_str, and you can see how I make a cookie out of it. Of course, this happens if the session is NEW. If the session is not new, then the hash cookie is retrieved using "$cookie = $query->cookie('H_VAL');" And we return the session object and the hash cookie. The mystery is why that cookie lozes it's name and gets a value of '$hash' rather than being made with the name H_VAL and the proper encrypted value originally put in $hash.

        $cookie = $query->cookie('H_VAL');

        This code from your example retrieves the value of the cookie with name 'H_VAL' and stores that value in the scalar variable $cookie. It does not create a cookie. See the section of the CGI documentation which starts "To retrieve a cookie" for examples and clarity.

        Its simple, because you wrote it that way
Re: Submiting multiple cookies on a redirect - how?
by Anonymous Monk on Aug 22, 2015 at 09:26 UTC