r.joseph has asked for the wisdom of the Perl Monks concerning the following question:
Hello! This is a pretty dumb question this time, but for some reason, I can't seem to get this to work correctly. I did everything by the docs, and yet I still can't seem to get it to work. Here is my problem:
I have a CGI program that uses cookies (hopefully merlyn won't -- me for not reading his latest Web Techniques article well enough *smiles*) to maintain a users 'login'. To create the cookies, this code is exectued:
my $q = new CGI;
my $cke1 = new CGI::Cookie(
-name => $in{usr},
-value => $val,
-expires => '+1h',);
print $q->header(-cookie=>$cke1);
which seems to work very well - by the way, the value is the users password MD5ed with some other secret stuff (I could tell you, but then I would have to kill you).
Now, I wanted to write a simple routine to log the person out, so that their little cookie would simply disapear into the magnetic oblivion that is the users hard drive. Easy, right? All I have to do is create another cookie, by the same name, with an expiration that is negative! So here is what I tried:
my $q = new CGI;
my $cke1 = new CGI::Cookie(
-name => $usr,
-value => $pwd,
-expires => '-1d',);
print $q->redirect(
-cookie=>$cke1,
-uri=>'http://mypage.com/my_login.html');
Now, as you can see, the cookie is the same, I just changed the expiration from an hour ahead of when the cookie was made (as was in the login code) to a day previous of when the code was executed, therefore telling the computer that that patricular cookie should have expired ASAP! Then, a simple redirect header takes the user to the login page, setting them up to log right back in!
Now, am I missing something here, because this seems like a perfectly logical way to do things, but it DOESN'T work! The logout code executes fine, but the cookie doesn't actually expire, so it is futile!
I am tired, and don't feel well, so I may be missing something, so please help me out fellow monks! Thanks!
r.
j
o
s
e
p
h
"Violence is a last resort of the incompetent" - Salvor Hardin, Foundation by Issac Asimov
Re: Loging a user out with CGI and Cookies?
by Beatnik (Parson) on Apr 16, 2001 at 01:21 UTC
|
I recommend looking into lhoward's node on Cookie logins... I personally found it pretty handy for my last few nodes...
Greetz
Beatnik
... Quidquid perl dictum sit, altum viditur. | [reply] |
Re: Loging a user out with CGI and Cookies?
by Keef (Sexton) on Apr 16, 2001 at 00:58 UTC
|
Well, I'm assuming that your not simply checking for the existence of a cookie with your CGI, but rather, you are looking for some specific verifier tht the cookie holds. Why not just recode your script to return an error page if the cookie holds an invalid verifier?
To clarify: Use a session-based system. When a user logs in, write them a cookie with the session ID. At that same time, write the session ID to a local file. When the user is logged out, erase the session ID from the file and if they try to return, their cookie will be checked. When the file is checked for the session ID that their cookie holds, the script won't find anything and can then tell the user to login again or buzzoff. | [reply] |
Re: Loging a user out with CGI and Cookies?
by merlyn (Sage) on Apr 16, 2001 at 15:52 UTC
|
You should definitely read my article on branding a browser with a cookie.
In there, I say something like: do not use the presence of a cookie to indicate a logged-in state, because the browser is free to ignore your requests to remove the cookie or expire it after a while.
Instead, simply ignore that particular cookie if it's sent in the future. This means you should use a cookie only as a key to a server-side database which shows the current state of logged-in or not.
-- Randal L. Schwartz, Perl hacker | [reply] |
|
Hi Merlyn,
maybe I am wrong but I thing that there is litle mistake in your code. Line 34:
my $cache = File::Cache->;new({namespace => 'cookiemaker',
Should be without ";": my $cache = File::Cache->new({namespace => 'cookiemaker',
This probabably happened by copying line 33.
Your servant
Li Tin O've Weedle
mad Tsort's philosopher | [reply] [d/l] [select] |
|
| [reply] |
|
Thanks merlyn - shortly after posting this, I broke out the latest "Web Techbniques" and re-read your article a couple times. Your right - as I was testing new ideas, I noticed that sometimes my browser did in fact ignore the cookie expiry all together. Therefore, I am going to need to implement some type of server side session info, has had been previously suggested.
Thanks for all the help!
r.
j
o
s
e
p
h
"Violence is a last resort of the incompetent" - Salvor Hardin, Foundation by Issac Asimov
| [reply] |
|
| [reply] |
|
Re: Loging a user out with CGI and Cookies?
by Dominus (Parson) on Apr 16, 2001 at 08:26 UTC
|
| [reply] |
Re: Loging a user out with CGI and Cookies?
by Trimbach (Curate) on Apr 16, 2001 at 02:49 UTC
|
I believe your problem is that you're trying to pass a cookie header at the same time as a redirect header. AFAIK that's a no-no: If a browser receives a "redirect" http header that's all that's processed, you don't get to pass any bonus information like cookie headers and such.
The solution is to recode your CGI to display a "you are logged out" message (which is good form anyway) instead of a redirect. Then you CAN pass the cookie, and all will be right with the world.
Gary Blackburn
Trained Killer | [reply] |
|
Trimbach, you may be half right. But it is
possible to accomplish this
without a two-step process.
First, the browser can indeed handle
the cookie header
and the "Location: ..." header line in the same
server response. The Location
line must come last and
it must end with two new-lines.
But I can find no indication in my quick
re-visiting of the docs that the CGI redirect
function allows the specification of a cookie along with
the redirect. (Update: but see the following
response by athomason.)
And the CGI pod says don't print a header
along with a redirect.
So I accomplish this manually:
print "Set-Cookie: $usr=x;expires=-1d\n";
print "Location: http://mypage.com/my_login.html\n\n";
There may be a gotcha here but I haven't run into it.
BTW, are you sure
that $in{usr} and $usr have
the same value? That would, of course, be crucial to
what you are trying to do. | [reply] [d/l] [select] |
|
As dvergin points out, browsers are perfectly capable of handling cookies sent with redirects. Fortunately, CGI.pm also supports it, though you have to dig a bit to be sure. The CGI pod indeed does not mention such a procedure, but it is supported. Browsing the code of the redirect sub in CGI.pm you can see:
#### Method: redirect
# Return a Location: style header
#
####
'redirect' => <<'END_OF_FUNC',
sub redirect {
my($self,@p) = self_or_default(@_);
my($url,$target,$cookie,$nph,@other) = $self->rearrange([[LOCATION
+,URI,URL],TARGET,COOKIE,NPH],@p);
$url = $url || $self->self_url;
my(@o);
foreach (@other) { tr/\"//d; push(@o,split("=",$_,2)); }
unshift(@o,
'-Status'=>'302 Moved',
'-Location'=>$url,
'-nph'=>$nph);
unshift(@o,'-Target'=>$target) if $target;
unshift(@o,'-Cookie'=>$cookie) if $cookie;
unshift(@o,'-Type'=>'');
return $self->header(@o);
}
Note in particular the -Cookie bit. And nicely enough, this actually works as intended. I've used bits like the following successfully:
$cookie = cookie(
-name => $COOKIE_NAME,
-value => $session_key,
-expires => $COOKIE_EXPIRE,
-path => $SCRIPT_PATH,
-domain => $SCRIPT_DOMAIN,
-secure => 0
);
...
print redirect( -uri => 'view.cgi', -cookie => $cookie );
I admit I'm not sure why OP's bit fails. r.jospeh, take a look at the cookie files for the site you're connecting to in order to make sure they're correct. Offhand, I'd suspect (like dvergin) a difference in $in{usr} and $usr is the problem. If not, you could set up a dirty HTTP server (with HTTP::Daemon, for instance) to see what's going on with your logout cookie. | [reply] [d/l] [select] |
Re: Loging a user out with CGI and Cookies?
by LiTinOveWeedle (Scribe) on Apr 16, 2001 at 15:17 UTC
|
use CGI;
$query = new CGI;
sub logout {
$cookie_expires = "-1s";
&cookie_create;
print $query->redirect( -uri => $redirect_to, -cookie => $cookie )
+;
}
sub cookie_create {
$cookie = $query->cookie(-name => $cookie_name,
-expires => $cookie_expires,
-domain => $cookie_domain,
-path => $cookie_path,
-value=>{ username => $username,
password => crypt($password, $us
+ername) }
);
}
As you can see cookie_create sub can be also used to create cookie not only to erase it. This worked well, if you want all script which verify login again csv flat file user database I can send it to you.
Good luck
Li Tin O've Weedle
mad Tsort's philosopher | [reply] [d/l] |
Re: Loging a user out with CGI and Cookies?
by dvergin (Monsignor) on Apr 16, 2001 at 06:21 UTC
|
r.joseph, while we are scratching around for an answer...
one more point that you do not make clear: How do you
know that "the cookie doesn't actually expire"? | [reply] |
|
Because I tested it locally with my cache folder open - the cookie didn't expire, and I will still able to access all the site's functions. However, many MANY good ideas have been brought up, and I thank everyone for your input. I think I will end up combining many facets of these suggestions to find a solution. Thanks a bunch!
r.
j
o
s
e
p
h
"Violence is a last resort of the incompetent" - Salvor Hardin, Foundation by Issac Asimov
| [reply] |
|
|