Forum Moderators: phranque

Message Too Old, No Replies

redirect requests to PHP script and avoid infinite loop

         

crimsontwo

11:17 pm on Dec 2, 2009 (gmt 0)

10+ Year Member



Hi,

I have the following rule that checks whether the visitor is authenticated:

RewriteRule ^controlpanel/(.*)$ controlpanel/checkLogin.php

After I am done authenticating the visitor, I use the header("Location: ...") command to proceed with the original request (REQUEST_URI). However, I end up in a loop.

What's the solution?

Also, would someone advise NOT to do authentication this way? My script checks for time between requests and other stuff, so that's why it's all done in 1 convenient location.

Thanks.

jdMorgan

11:44 pm on Dec 2, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Your rule rewrites all requested URL-paths that start with "controlpanel/" followed by anything or nothing else to controlpanel/checkLogin.php, which also matches the rule's pattern, so if this code is in .htaccess, it will loop internally (internal rewrite loop). If this code is in a server config file, then it shouldn't loop.

Next, if the URL you send with your Location header matches that RewriteRule pattern, it will loop externally (redirection-authentication loop).

To fix the first problem:


RewriteCond $1 !^checkLogin\.php$
RewriteRule ^controlpanel/(.*)$ controlpanel/checkLogin.php [L]

I can't advise on the second problem if it exists, since you didn't specify the Location header URL-path.

Jim

crimsontwo

9:58 pm on Dec 3, 2009 (gmt 0)

10+ Year Member



Thanks.

Am I dreaming or there is also a way to execute another redirect based on the result of the first redirect?

Let's say I do all my magic in PHP and then instead of redirecting the visitor using the "header" command, I let .htaccess do that? If PHP returns "true", then redirect to A, if "false", then to B.

g1smd

10:03 pm on Dec 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Once control has passed to the script, the script will need to send headers and page content.

It is too late for .htaccess rules to come into play. That process ends before any content handling starts.

Additionally, multiple chained redirects are generally a Bad Thing.

crimsontwo

10:07 pm on Dec 3, 2009 (gmt 0)

10+ Year Member



that's what I thought.

by the way, the rule doesn't seem to work.

==============
in PHP I have the following:

header("Location: ".$_SERVER['REQUEST_URI']);

in .htaccess:

Options +FollowSymlinks
RewriteEngine On

# Control Panel rules
RewriteCond $1 !^checkLogin\.php$
RewriteRule ^controlpanel/(.*)$ controlpanel/checkLogin.php [L]
==============

it goes into a loop (in IE) and FireFox gives an error saying that a redirect won't work.

g1smd

10:32 pm on Dec 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Firstly your HEADER makes a 302 redirect. You need another HEADER before that one to set the 301 status. Make sure this PHP redirect also explicitly sets the domain name, and fixes the www or non-www in the redirected URL.

Secondly, you'll need Live HTTP Headers for Firefox to see what the server response codes and redirect URLs are, to work out where the redirect loop is coming from.

jdMorgan

11:03 pm on Dec 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Right, so after the redirect back to the originally-requested URL is invoked by your script, how is mod_rewrite supposed to know *not* to rewrite the request from the now-authenticated-user back to the authentication script again? Since a redirect ends the current HTTP transaction and tells the client to begin a new one, some method of tracking the user-authorized/user-not-authorized state has to be implemented.

Your authentication script will need to set a client-side cookie that mod_rewrite can test, so that this rewrite->redirect loop can be avoided.

Jim

crimsontwo

11:14 pm on Dec 3, 2009 (gmt 0)

10+ Year Member



Jim, that makes sense but I just don't know how to implement that considering that I want to channel ALL requests through my PHP script.

Let's say I authenticate the user and create a cookie; mod_rewrite will check for that cookie and if it doesn't exist, redirect to my PHP script. However, I also want to check time between requests and if its > N, then have PHP authenticate the user.

Basically, I am looking for a code that will:

1) redirect everything to a single PHP script
2) allow that PHP script to redirect to the original request without meeting a loop

Thanks.

jdMorgan

11:28 pm on Dec 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If you want to process all requests through one script, then set a cookie and let your script check it. Cookies can be set for a single browser session, or for a specified time (so you don't need a 'time check' in your script). Do a search for "HTTP Cookie" if you don't know how cookies work -- The old Netscape documentation is one of the shortest, most-accurate resources.

Jim

crimsontwo

4:19 pm on Dec 4, 2009 (gmt 0)

10+ Year Member



Jim, but I would still have to redirect everything through a single script if I were to "set a cookie and let your script check it".

One other reason why I want to redirect all requests through my script is because I checked if the visitor has JS enabled, and also if the current request came from the same IP as the previous. Basically, I check for a lot of things in my PHP script and I don't really understand how I can do this with a cookie. All the information is stored in the SESSION array.

jdMorgan

4:41 pm on Dec 4, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I am talking about your "one script" not a second script.
In your script, test for the cookie. If it's not set, run the authentication code, then set the cookie. Then do all your other stuff. This isn't as hard as it may appear to you, it's just saving a "yes this user is authenticated, don't keep asking him to log-in repeatedly" cookie on the client side.

If you don't know how to write and read cookies, the read the Netscape document I mentioned, and then search our PHP forum (and others) for cookie-handling code. That should give you a very good start on adding the necessary feature.

Jim

crimsontwo

4:48 pm on Dec 4, 2009 (gmt 0)

10+ Year Member



Jim, I know how to set/read cookies.

Perhaps I am not making myself clear: I have _1_ script that does it all. It checks for authentication, for time between requests, for JavaScript, for IP (previous request/current request), and bunch of other things. Reason? Because any of these parameters may change between requests.

So, that is the reason why I want _all_ requests to be redirected to that script. Once the check is done and everything is OK, the script will redirect to the location originally requested. However, this is where I get stuck: mod_rewrite starts looping.

If I understood you correctly, I will have to create a cookie EVERY time the request is redirected to my script, correct? So, let's say, the visitor makes 20 requests a minute, hence 20 times I will have to set a cookie? What about performance hit? 100 users x 20 requests/minute = 2000 set/read cookie operations.

jdMorgan

5:27 pm on Dec 4, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It is not mod_rewrite or "just mod_rewrite" that is looping. Your script is involved as well. Your script must "know" that it has already authenticated the user, and then quit 'redirecting'.

You have stated that you want *ALL requests rewritten to your script" and that's what you mod_rewrite code does. If this results in a loop, it's because your script is continually "redirecting to the originally-requested URL" and causing a new HTTP request, which then gets rewritten back to the script. So as long as you rewrite *ALL* HTTP requests to your script, then it is up to the script to quit "redirecting to the originally-requested URL" when it no longer needs to do so -- and that is the function of the proposed cookie.

I'm sorry if it's not clear, but I can't say it any differently. It'll be up to you to understand what I wrote, even if I didn't write it well.

Jim