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