You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Shimon Rura <sh...@rura.org> on 2000/10/15 10:11:08 UTC

Apache::ASP cookieless sessions question

Hi, Throughout my web pages I provide a link for the user to login, which
goes to a username/password check which then forwards the user back to the
original page where he clicked "login".  The login link is implemented with:

<a href="/user/login?return_url=<%=$Server->URLEncode($ENV{REQUEST_URI})%>">
login
</a>

And of course /user/login (an ASP script) will eventually
$Response->Redirect() the client to the original URL.  The only problem is
that if a client's browser has cookies disabled, the ?session-id=blah
doesn't get encoded into their URL (thanks to SessionQueryParse) when they
first type it the URL.  So if they type "www.foo" and click login, it just
takes them back to "www.foo" without preserving the session-id, and it looks
like they haven't logged in at all (and indeed they are running under a
different session-id).  If they load "www.foo" and click on a link which I
typed in as "www.foo" they stay in the same session because the link becomes
"www.foo?session=blah".  Then logging in works fine.

So, is there a way I can make the Apache::ASP handler (or some other
component of Apache) redirect cookieless clients to scripts whose URIs
contain a session id?

The other related problem is that when a client that allows cookies visits a
page for the first time, all their link URLs have session-ids parsed into
them unnecessarily.

This is the method that I have in mind that I think would resolve these
issues.  A hit to a web page with session tracking does this:

Hit to "www.foo/bar".  If client delivers session-id cookie, deliver plain
page for cookied clients.  If query string contains session-id, deliver a
page with session-ids parsed into links for cookieless clients.  If client
delivers no cookie and session-id is not in URL, set cookie and redirect to
self-URL with session-id parsed in.

Even this isn't perfect though, since the URI will sometimes unnecessarily
contain the session-id value for cookied browsers.  This will still
contaminate the return_url for my login procedure, but at least the link and
image URLs from the first page won't be uglified.  

The perfect solution would be to redirect the client to the self-URL without
the session-id in their query string when *both* a cookie is sent and a
session-id is in the query string.  Combined with the method above, this
would result in a cookied browser doing:

1. user types "www.foo", server receives no cookie
2. server sends cookie and forwards to "www.foo?session-id=blah"
3. server receives cookie and forwards to "www.foo"
4. server delivers plain "www.foo"

And a cookieless browser:

1. user types "www.foo", server receives no cookie
2. server sends cookie and forwards to "www.foo?session-id=blah"
3. server receives no cookie and delivers request for "www.foo" with
session-ids parsed into all links

Basically, the stable cases (sending cookies OR sending ids in query-string)
are fine, it's just the cases of neither or both being sent that need to be
fixed.

So... can I make these sorts of things happen?  Should I care?  Is there a
way I can find out whether the user's browser is cookied for session-id from
within the ASP script?

Thanks,
shimon.

p.s. Apache::ASP is great!  I love it!  What a timesaver and so easy to work
with!

Re: Apache::ASP cookieless sessions question

Posted by Joshua Chamas <jo...@chamas.com>.
Shimon Rura wrote:
> 
> Hi, Throughout my web pages I provide a link for the user to login, which
> goes to a username/password check which then forwards the user back to the
> original page where he clicked "login".  The login link is implemented with:
> 
> <a href="/user/login?return_url=<%=$Server->URLEncode($ENV{REQUEST_URI})%>">
> login
> </a>
> 
> And of course /user/login (an ASP script) will eventually
> $Response->Redirect() the client to the original URL.  The only problem is
> that if a client's browser has cookies disabled, the ?session-id=blah
> doesn't get encoded into their URL (thanks to SessionQueryParse) when they
> first type it the URL.  So if they type "www.foo" and click login, it just
> takes them back to "www.foo" without preserving the session-id, and it looks
> like they haven't logged in at all (and indeed they are running under a
> different session-id).  If they load "www.foo" and click on a link which I
> typed in as "www.foo" they stay in the same session because the link becomes
> "www.foo?session=blah".  Then logging in works fine.
> 

SessionQueryParse runtime session-id insertion into query strings
to handle cookieless clients should cover $Response->Redirect() URLs
too.  The problem is that you are redirecting to an absolute URL, 
where the matching algorithm normally covers only links relative
to the current server.  The solution is to configure SessionQueryParseMatch
with a regexp that matches URLs that you also want session-ids inserted 
into, so you can handle what the user typed in.

> The other related problem is that when a client that allows cookies visits a
> page for the first time, all their link URLs have session-ids parsed into
> them unnecessarily.
> 

There is an optimization that if the client presents any cookies at
all, then the session-ids won't be inserted into URLs.  So in 
Script_OnStart, you can check for a permanent cookie, and if the client 
doesn't have it, then set one.  Then all subsequent visits, the client will 
not have session-id's parsed in.  Also, you can provide a "cookie shield"
for your site, by marking a value in $Session, like $Session->{CookiesOn} = 1
and if set do nothing, otherwise, set, and redirect to current URL; with
SessionQueryParse enabled, this should be simple logic, as they will
always have a session-id on the next request, and that value will be marked.

> This is the method that I have in mind that I think would resolve these
> issues.  A hit to a web page with session tracking does this:
> 
> Hit to "www.foo/bar".  If client delivers session-id cookie, deliver plain
> page for cookied clients.  If query string contains session-id, deliver a
> page with session-ids parsed into links for cookieless clients.  If client
> delivers no cookie and session-id is not in URL, set cookie and redirect to
> self-URL with session-id parsed in.
> 

I think it is better to do these things per site, as redirects
do not cover form based scenarios, as form POST input will be lost,
so its not a truly generic solution.  It may be that a site running
SessionQueryParse will want to handle form requests on the first
incoming request, I think the better hack is setting the permanent
cookie.

> The perfect solution would be to redirect the client to the self-URL without
> the session-id in their query string when *both* a cookie is sent and a
> session-id is in the query string.  Combined with the method above, this
> would result in a cookied browser doing:
> 
> 1. user types "www.foo", server receives no cookie
> 2. server sends cookie and forwards to "www.foo?session-id=blah"
> 3. server receives cookie and forwards to "www.foo"
> 4. server delivers plain "www.foo"
> 

That's a lot of requests to serve up a first page to a site.
Average content web sites have something like 2-3 page requests 
per user, and we are creating 3 request just for the first hit,
doubling the number of requests necessary to handle the user.
I think the logic here is simple if you want to implement it,
but I worry about it being a generic solution.

# assumes SessionQueryParse enabled
sub Script_OnStart {
  # use permanent cookie for a hint, if available
  unless(%{$Request->{Cookies}} || $Session->{CookiesOn}) {
    $Session->{CookiesOn} = 1;
    $Response->{Cookies}{Perm} = { Value => 1, Expires => 86400 * 365 };
    $Response->Redirect(
		$Server->URL(
			&File::Basename::basename($0), 
			$Request->{QueryString)
			)
	);
  }
}

If SessionQueryParse weren't enabled, then for a cookieless
client, this solution would loop infinitely, and there needs
to be other logic enabled to make this happen.

> So... can I make these sorts of things happen?  Should I care?  Is there a
> way I can find out whether the user's browser is cookied for session-id from
> within the ASP script?
> 

I think the SessionQueryParseMatch will be key for you, as well
as the permanent cookie trick. 

> p.s. Apache::ASP is great!  I love it!  What a timesaver and so easy to work
> with!

Glad to hear it!

-- Joshua

_________________________________________________________________
Joshua Chamas			        Chamas Enterprises Inc.
NodeWorks >> free web link monitoring	Huntington Beach, CA  USA 
http://www.nodeworks.com                1-714-625-4051